home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-serious-
/
programming
/
other
/
fd2pragma
/
source
/
fd2pragma.c
next >
Wrap
Text File
|
2000-02-28
|
192KB
|
6,688 lines
#define NAME "FD2Pragma"
#define VERSION "2"
#define REVISION "100"
#define DATE "17.02.2000"
//#define DEBUG
//#define DEBUG_OLD
/* Programmheader
Name: FD2Pragma
Author: SDI
Distribution: PD
Description: creates pragmas files, lvo files and stub functions
Compileropts: -
Linkeropts: -gd -l amiga
1.2 : added pragmas for the Dice compiler. Available via switch "Dice".
added switches "Aztec", "SAS" and "Maxon": Maxon and Aztec just
turn on the default (except that Maxon expects pragma files to be
called "xxx_pragmas.h" instead of "xxx_lib.h"), SAS is equal to
Dice, except that SAS supports the pragma tagcall.
2.0 : Added support for tag functions. See the docs for details.
Author until this version:
Jochen Wiedmann
Am Eisteich 9
72555 Metzingen (Germany)
Tel. 07123 / 14881
2.1 19.08.96 : now made by SDI, added correct __MAXON__ support and
support for StormC++, added auto recognition of tagcall functions
changed the CLI interface completely
2.2 21.08.96 : fixed a lot of errors, added debug code
2.3 22.08.96 : little changes
2.4 24.08.96 : added proto-file creation
2.5 25.08.96 : added syscall and fix for functions ending in ...DMA
2.6 26.08.96 : fixed some errors, added CLIB parameter (used later for
CSTUBS)
2.7 01.09.96 : added correct Storm definition, added CLIB scan
2.8 02.09.96 : added assembler stub functions, added first ASM-stub code
2.9 04.09.96 : added Comment-Support
2.10 05.09.96 : changed CSTUB creation a bit
2.11 07.09.96 : speeded up output, reduced number of strndup calls
2.12 26.09.96 : pressing CTRL-C in early startup brought a wrong error
message - fixed
2.13 30.09.96 : made RegNames field to RegNames string - shorter Exe-file
2.14 01.10.96 : made SPECIAL 6 default, COMMENT also in LVO files
2.15 13.10.96 : corrected an error text
2.16 14.10.96 : added correct comment support and PRIVATE option
2.17 19.10.96 : now Maxon-compiled in Small data mode
2.18 22.10.96 : removed EXTERNC in Storm, Maxon and all pragmas, corrected
the texts, again SAS compiled
2.19 26.10.96 : added option to create FD files out of pragma files,
reworked a lot in the source
2.20 27.10.96 : fixed errors of previous version
2.21 28.10.96 : fixed error in CLIB scan
2.22 27.11.96 : SPECIAL numbers for lib and ASM code were wrong, removed
bug in Tag function stubs
2.23 06.12.96 : lib and stub creation still was wrong
2.24 31.12.96 : formed stub libs matching C++ file names, corrected CLIB
scan errors
2.25 04.01.97 : added HEADER option (I was asked for)
2.26 05.01.97 : added HEADER scan (in old file) and auto inserting
2.27 10.01.97 : stub functions missed register saving, outfuncs skip now,
when error occured (makes lots of error checking obsolete)
2.28 11.01.97 : forgot to add offset made by register saving
2.29 18.01.97 : now libtags and amitags defines only, when at least 1
tagfunc
2.30 13.02.97 : added local library base functions, rearranged SPECIAL
options, fixed some bugs
2.31 15.02.97 : corrected bugs inserted in previous version
2.32 16.02.97 : and again bug fixes, still didn't work
2.33 18.02.97 : corrected texts, added SPECIAL 28
2.34 25.03.97 : corrected Pragma --> FD file conversion, added ##shadow
2.35 26.03.97 : added STORMFD option, COMMENT, PRIVATE work again
2.36 29.03.97 : corrected *tagcall scan a bit
2.37 20.06.97 : added PASCAL stub lib production (SPECIAL 14, 15)
2.38 01.07.97 : fixed ##end handling
2.39 20.07.97 : added better proto file (__GNUC__ inline and pragma call),
removed C++ comments
2.40 24.11.97 : added new basenames to the list (devices and resources),
added tag-exception name checking (dos, utility libraries)
2.41 27.11.97 : fixed little bug with private functions, CSTUBS now
special option and no longer commandline arg, SPECIAL 10-15 got
numbers 11-16 (Sorry)
2.42 28.11.97 : Added two new warnings for CLIB
2.43 12.12.97 : faster FD file scan, one new warning
2.44 19.12.97 : fixed MODE settings for SPECIAL 15,16
2.45 30.01.98 : added function recognition, included inline creation,
inline stuff is based on fd2inline 1.11 (incomplete)
2.46 31.01.98 : continued inline stuff, fixed clib functions
2.47 05.02.98 : completed inline stuff, added alias names for dos functions
2.48 06.02.98 : changed Func interface - flags instead of tagmode
2.49 10.02.98 : fixed inline generation a bit, added SORTED argument,
RegNames got strings again
2.50 11.02.98 : bug-fixes, still did not work completely, hopefully got
all now
2.51 12.02.98 : and bug-fixes again :-(
2.52 15.02.98 : changed sorting order of arguments
2.53 20.02.98 : some code style changes
2.54 25.02.98 : added SMALLDATA model, removed 5 global variables (better
style), stub libs use MOVEM when possible, own MemRemember function
2.55 26.02.98 : bug fixes
2.56 15.03.98 : added FPU support
2.57 17.03.98 : added NOFPU keyword
2.58 19.03.98 : little fixes
2.59 20.03.98 : added enum and external type definitions defines
2.60 22.03.98 : added external types file scan
2.61 23.03.98 : fixed SAS flibcall, added FPU stubs
2.62 28.03.98 : bug fix with NOFPU and new option FPUONLY, total new clib
handling
2.63 29.03.98 : really lots of bug fixes, There are so much problems.
A better definition format would have been wonderful.
2.64 05.04.98 : bug fixes
2.65 07.04.98 : fixed Enforcer hit
2.66 08.04.98 : bug fix with type detection
2.67 20.04.98 : added GNU-only stuff
2.68 28.04.98 : SPECIAL 8 defaults to SAS-C names now
2.69 25.05.98 : added PowerUP stuff support
2.70 28.05.98 : added SAS PowerUP stuff, fixed error with function
detection in CLIB scan
2.71 30.05.98 : added PowerUP Inlines
2.72 12.06.98 : sorting turns of COMMENT now
2.73 05.07.98 : added first FPC stuff, added HEADER to PowerUP stuff,
added PASCAL header scan
2.74 06.07.98 : finished FPC stuff
2.75 07.07.98 : bug fixes for FPC stuff
2.76 09.07.98 : style changes for FPC stuff, bug fixes
2.77 11.07.98 : hopefully last FPC bug removed
2.78 23.07.98 : style changes and bug fixes for FPC stuff, more comments
2.79 10.08.98 : bug fix, when TO was used with a directory, clib got
wrong path if it was a relative path description
2.80 16.08.98 : now prints better error when filopen failed
2.81 26.10.98 : added BMAP files for BASIC, CODE needs to use large mode
now :-(
2.82 28.10.98 : optimizations and bug fixes
2.83 31.12.98 : fixed powerup stuff a bit
2.84 05.01.99 : fixed bug in Lib creation, when Dx/Ax and FPx were mixed
2.85 06.01.99 : added recognition of names ending in MESA, added notagcall
comment support, void functions no longer can be tagcall
2.86 10.01.99 : added BGUI special funcs, fixed bug in SPECIAL 42 code
2.87 12.01.99 : added asm-text (SECTION), moved 12-17 to 13-18
2.88 17.01.99 : better type detection, added some more basenames, some
little bug fixes, new makefile reduces file size a lot
2.89 17.07.99 : added union support
2.90 12.11.99 : added new motorola syntax, opt040 and vbcc inlines
2.91 13.11.99 : Now supports changes in OS3.5 includes, why the hell must
such changes be? I thought new includes will bring cleanup and not
cleandown. And the reported bugs are still unfixed, but there are
new ones!, bug-fixes
2.92 14.11.99 : added PPC-WOS library text and code, FD-creation moved from
80 to 200 (now finally! - there should be enough free number space),
added VBCC-PUP text generation
2.93 15.11.99 : added CheckError function, moved DisplayInfoHandle to
types definition file
2.94 16.11.99 : added first VBCC-PowerUP-Lib production stuff, only ELF
tables missing
2.95 17.11.99 : finished PowerUP stub stuff, startet PPC-ABI stuff
2.96 18.11.99 : little bug fixes
2.97 19.11.99 : added SECTION keyword, moved 11-18 to 12-17, ahh 3 releases
more and we get an anniversary, my first program using third revision
digit :-)
2.98 20.11.99 : added VBCC-WOS-Code for PPC libs
2.99 25.11.99 : bug fixes
2.100 17.02.00 : fixed bug for VBCC inlines
*/
/* A short note, how FD2Pragma works.
Working mode for SPECIAL 200 is a bit different!
The main function parses arguments. Switches are converted into FLAG_XXX values
and stored in global "Flags" variable. SPECIAL numbers are parsed and are used
to call a CreateXXX function, with its interface depending on the need of
arguments (Some have 2, some none, ...). Before SPECIAL arguments are parsed,
FD2Pragma loads FD file and scans it using ScanFDFile(). If SORTED is specified,
the list gets sorted directly afterwards. IF CLIB argument is given, the clib
file is scanned before FD file and a clib list is created. Now SPECIAL is parsed
and mode is set to any of the MODUS_XXX values. Also the destination file name
is created if not given. The destination file is opened now. The mode variable
is used to determine the correct CreatXXX function, which is called afterwards.
This function produces file headers and stuff like that and calls CallFunc to
process each FD entry. CallFunc gets 3 arguments. First the workmode (TAG,
NORMAL, BOTH). Second the comment method (for C it is "/%s *.\n" [. means /],
for ASM it is "\n%s", no comment is reached with 0 argument). The last is most
important. It is the function pointer to a function creating the entries.
These functions have always the same interface and are called through CallFunc
only! They create an entry for the specified function (e.g. FD entry).
Parsing special functions, adding comments, checking for tag-functions, ...
is done by CallFunc. It is no problem to call CallFunc multiple with different
function pointers (as is done for SPECIAL 6 pragmas).
The functions can use DoOutput to output texts in printf style or DoOutputDirect
to output all data in fwrite style. Buffering is done automatically.
FD2Pragma has its own memory managment. All memory must be allocated using
AllocListMem and is freed automatically. This is especially useful for DupString
function, which is used in FD in CLIB scanner.
Normally this source-file is to big and should be splitted in different files
compiled alone and linked together. :-)
*/
#include <proto/exec.h>
#include <proto/dos.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <dos/doshunks.h>
#define SDI_TO_ANSI
#include "SDI_ASM_STD_protos.h"
#include "SDI_defines.h"
#include "SDI_compiler.h"
#ifdef __MAXON__ /* needed for -gd option */
#include <linkerfunc.h>
#endif
#define TEXT_SAS "__SASC" /* verified */
#define TEXT_SAS_60 "__SASC_60" /* verified */
#define TEXT_MAXON "__MAXON__" /* verified */
#define TEXT_STORM "__STORM__" /* verified */
#define TEXT_DICE "_DCC" /* in 2.0 code */
#define TEXT_AZTEC "AZTEC_C" /* verified */
#define TEXT_GNUC "__GNUC__" /* verified */
#define TEMPSIZE 1024
#define FLAG_EXTERNC (1<< 0) /* add externc statements */
#define FLAG_SYSCALL (1<< 1) /* create SAS-C syscall pragmas */
#define FLAG_DOCOMMENT (1<< 2) /* do comment processing */
#define FLAG_PRIVATE (1<< 3) /* also use private functions */
#define FLAG_LOCALREG (1<< 4) /* local file uses register call */
#define FLAG_STORMFD (1<< 5) /* FD file uses strange Storm format */
#define FLAG_PASCAL (1<< 6) /* library creation with PASCAL style */
#define FLAG_SMALLDATA (1<< 7) /* libraries use small data modell */
#define FLAG_DONE (1<< 8) /* destination file is not empty */
#define FLAG_INLINENEW (1<< 9) /* produce new style inlines */
#define FLAG_INLINESTUB (1<<10) /* produce stubs style inlines */
#define FLAG_NOFPU (1<<11) /* do not allow FPU registers */
#define FLAG_DIDERROR (1<<12) /* one error already printed, don't print 2nd */
#define FLAG_FPUONLY (1<<13) /* only use FPU registers */
#define FLAG_GNUPRAG (1<<14) /* insert inline call into pragma file */
#define FLAG_POWERUP (1<<15) /* create Phase5 PowerUP files */
#define FLAG_ASMSECTION (1<<16) /* create SECTIONS in Asm code */
#define FLAG_NEWSYNTAX (1<<17) /* new motorola syntax */
#define FLAG_NOMOVEM (1<<18) /* 68040 optimization, don't use MOVEM */
#define FLAG_WOSLIBBASE (1<<19) /* first arg is libbase for VBCC WOS */
#define FLAG_NOPPC (1<<20) /* do not allow PPC functions */
#define FLAG_PPCONLY (1<<21) /* only take PPC functions */
#define FLAG_NOSYMBOL (1<<23) /* do not create symbol section for libs */
#define FUNCFLAG_NORMAL (1<<29) /* normal function */
#define FUNCFLAG_TAG (1<<30) /* a tagcall function */
#define FUNCFLAG_ALIAS (1<<31) /* an alias name for previous function */
/* Different modes the main program uses, one for each different file
type (except for those done with one function and flag settings). */
#define MODUS_STUBTEXT 1
#define MODUS_STUBCODE 2
#define MODUS_LOCALDATA 3
#define MODUS_PRAGMA 4
#define MODUS_CSTUB 5
#define MODUS_SASPOWER 6
#define MODUS_PROTOPOWER 7
#define MODUS_BMAP 8
#define MODUS_PASCAL 9
#define MODUS_VBCCINLINE 10
#define MODUS_VBCCPUPLIB 11
#define MODUS_LVOLIB 12
#define MODUS_LVO 50 /* and 51 and 52 and 53 */
#define MODUS_PROTO 60 /* and 61 to 67 */
#define MODUS_INLINE 70 /* and 71 and 72 */
#define MODUS_VBCC 80 /* and 81 to 84 */
#define MODUS_ERROR 100
#define ABI_M68K 1
#define ABI_PPC 2
#define ABI_PPC2 3
#define ABI_PPC0 4
/* call types for CallFunc */
#define TAGMODE_NORMAL 0 /* produce normal functions only */
#define TAGMODE_TAGS 1 /* produce only tag functions */
#define TAGMODE_BOTH 2 /* produce both types */
/* types specifying name method for pragma creation */
#define PRAGMODE_PRAGLIB 1
#define PRAGMODE_PRAGSLIB 2
#define PRAGMODE_PRAGSPRAGS 3
#define PRAGMODE_NONE 4
#define BIAS_OFFSET 6 /* value to switch from one to next function */
#define EXTTYPESFILE "FD2Pragma.types"
#define EXTTYPESFILE2 "PROGDIR:FD2Pragma.types"
#define FDFILEEXTENSION "_lib.fd"
#define PARAM "FROM=INFILE/A,SPECIAL/N,MODE/N," \
"TO/K,CLIB/K,HEADER/K," \
"AMICALL/K,LIBCALL/K,AMITAGS/K,LIBTAGS/K," \
"COMMENT/S,EXTERNC/S,FPUONLY/S,NEWSYNTAX/S,NOFPU/S," \
"NOPPC/S,NOSYMBOL/S,OPT040/S,PPCONLY/S,PRIVATE/S," \
"SECTION/S,SMALLDATA/S,SORTED/S,STORMFD/S,USESYSCALL/S"
const STRPTR RegNames[] = {
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
"fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7",
};
const STRPTR RegNamesUpper[] = {
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"FP0", "FP1", "FP2", "FP3", "FP4", "FP5", "FP6", "FP7",
};
enum Register_ID {
REG_D0, REG_D1, REG_D2, REG_D3, REG_D4, REG_D5, REG_D6, REG_D7,
REG_A0, REG_A1, REG_A2, REG_A3, REG_A4, REG_A5, REG_A6, REG_A7,
REG_FP0, REG_FP1, REG_FP2, REG_FP3, REG_FP4, REG_FP5, REG_FP6, REG_FP7,
};
#define MAXREGPPC 26
#define MAXREG 24 /* maximum registers of 68K */
#define MAXREGNF 16 /* maximum register number without float regs */
struct Args
{
STRPTR INFILE;
ULONG* SPECIAL;
ULONG* MODE;
STRPTR TO;
STRPTR CLIB;
STRPTR HEADER;
STRPTR AMICALL;
STRPTR LIBCALL;
STRPTR AMITAGS;
STRPTR LIBTAGS;
ULONG COMMENT;
ULONG EXTERNC;
ULONG FPUONLY;
ULONG NEWSYNTAX;
ULONG NOFPU;
ULONG NOPPC;
ULONG NOSYMBOL;
ULONG OPT040;
ULONG PPCONLY;
ULONG PRIVATE;
ULONG SECTION;
ULONG SMALLDATA;
ULONG SORTED;
ULONG STORMFD;
ULONG USESYSCALL;
};
struct ShortList {
struct ShortList *Next;
};
struct ShortListRoot {
struct ShortList *First;
struct ShortList *Last;
ULONG Size;
};
#define AMIPRAGFLAG_PUBLIC (1<< 0) /* is a public function */
#define AMIPRAGFLAG_A6USE (1<< 1) /* A6 is used for this function */
#define AMIPRAGFLAG_A5USE (1<< 2) /* A5 is used */
#define AMIPRAGFLAG_A4USE (1<< 3) /* A4 is used */
#define AMIPRAGFLAG_D7USE (1<< 4) /* D7 is used */
#define AMIPRAGFLAG_ARGCOUNT (1<< 5) /* when double args, ... */
#define AMIPRAGFLAG_DIDARGWARN (1<< 6) /* We printed a argcount warning */
#define AMIPRAGFLAG_FLOATARG (1<< 7) /* It has a float argument */
#define AMIPRAGFLAG_DIDFLOATWARN (1<< 8) /* We printed a float warning */
#define AMIPRAGFLAG_NOCLIB (1<< 9) /* No clib definition found */
#define AMIPRAGFLAG_CLIBARGCNT (1<<10) /* CLIB argument count error */
#define AMIPRAGFLAG_PPC (1<<11) /* This is an PPC function */
#define AMIPRAGFLAG_DIDPPCWARN (1<<12) /* we already printed ppc warning */
#define AMIPRAGFLAG_PPC0 (1<<13) /* type PPC0 */
#define AMIPRAGFLAG_PPC2 (1<<14) /* type PPC2 */
struct AmiPragma {
struct ShortList List;
UWORD Bias;
UWORD Line;
ULONG Flags;
STRPTR FuncName;
STRPTR TagName;
struct Pragma_AliasName * AliasName; /* possible second name */
UWORD NumArgs; /* register numbers */
UWORD CallArgs; /* argument number in fd file */
struct AmiArgs
{
STRPTR ArgName;
UWORD ArgReg;
} Args[MAXREGPPC];
};
struct Comment {
struct ShortList List;
STRPTR Data;
UWORD Bias;
};
struct PragList {
struct ShortList List;
struct ShortListRoot Data; /* contains list of PragData */
STRPTR Basename;
};
struct PragData {
struct ShortList List;
struct ShortListRoot Name;
ULONG NumNames;
ULONG Bias;
ULONG NumArgs;
UBYTE ArgReg[MAXREG];
};
struct FDData {
STRPTR Name;
STRPTR Basename;
ULONG Bias;
ULONG Mode; /* 0 = Normal, != 0 is TagName */
ULONG NumArgs;
UBYTE ArgReg[MAXREG];
};
/* These CPP types match the strings used for CPP name creation. The
defines are used both for name creation and type specification. */
#define CPP_TYPE_VOID 'v' /* void, VOID */
#define CPP_TYPE_BYTE 'c' /* char, BYTE */
#define CPP_TYPE_WORD 's' /* short, WORD */
#define CPP_TYPE_LONG 'j' /* long, LONG */
#define CPP_TYPE_FLOAT 'f' /* float, FLOAT */
#define CPP_TYPE_DOUBLE 'd' /* double, DOUBLE */
#define CPP_TYPE_STRUCTURE 0
#define CPP_TYPE_VARARGS 'e'
/* These types are for string creation only. */
#define CPP_TYPE_ENUM 'E'
#define CPP_TYPE_CONST 'C'
#define CPP_TYPE_FUNCTION 'F'
#define CPP_TYPE_POINTER 'P'
#define CPP_TYPE_UNSIGNED 'U'
#define CPP_TYPE_FUNCEND 'p'
#define CPP_TYPE_REGISTER 'r'
/* Some flags to be used in CPP_NameType->Flags. */
#define CPP_FLAG_UNSIGNED (1<<0) /* is an unsigned variable */
#define CPP_FLAG_CONST (1<<1) /* type is const */
#define CPP_FLAG_STRPTR (1<<2) /* this variable contains a STRPTR */
#define CPP_FLAG_POINTER (1<<3) /* the variable is a pointer */
#define CPP_FLAG_ENUM (1<<4) /* it is a enumeration */
#define CPP_FLAG_STRUCT (1<<5) /* it is a structure */
#define CPP_FLAG_UNION (1<<6) /* it is a union */
#define CPP_FLAG_FUNCTION (1<<7) /* it is a function */
#define CPP_FLAG_BOOLEAN (1<<8) /* in truth this element is bool */
/* STRPTR is defined different under C and CPP -> I have to create two
names, one time unsigned char *, one time signed char *, when somewhere
a STRPTR occurs */
struct CPP_NameType { /* structure to describe a argument type */
STRPTR StructureName; /* if a structure or enum only */
STRPTR FuncArgs; /* arguments of function - unterminated */
STRPTR TypeStart; /* start of this type */
UWORD StructureLength; /* length of the structure name */
UWORD ArgsLength; /* length of FuncArgs */
UWORD TypeLength; /* length of this type */
UWORD FullLength; /* length of complete type */
UWORD PointerDepth; /* number of * in type */
UWORD Flags; /* see above flags */
UBYTE Type; /* see above defines */
};
struct ClibData { /* structure to describe data in CLIB file */
struct ClibData * Next; /* The next entry in this list */
STRPTR FuncName; /* name of the function */
ULONG NumArgs; /* number of arguments */
struct CPP_NameType ReturnType; /* data for return type */
struct CPP_NameType Args[MAXREGPPC+1]; /* data for argument types */
};
struct CPP_ExternNames { /* structure for EXTTYPESFILE data */
struct CPP_ExternNames * Next; /* The next entry in this list */
STRPTR Type; /* The unknown type */
struct CPP_NameType NameType; /* The replacement */
};
struct CPP_TypeField { /* structure for internal defined types */
STRPTR Text; /* name of the type */
UWORD Length; /* length of the name string */
UWORD Flags; /* CPP_FLAG flags */
UBYTE Type; /* CPP_TYPE value */
};
struct Proto_LibType { /* structure to define structure type of base vars */
STRPTR BaseName; /* name of the library base */
STRPTR StructureName; /* name of the structure to be used */
};
struct Pragma_ExecpName { /* structure to specify special tagnames */
STRPTR FunctionName; /* function name */
STRPTR TagName; /* tag name to be used for this function */
}; /* TagName 0 is valid as well to disable tagfunctions */
struct Pragma_AliasName {
STRPTR FunctionName;
STRPTR AliasName;
ULONG Type;
};
#define NTP_NORMAL 0 /* no tags/args */
#define NTP_TAGS 1 /* TagFunction */
#define NTP_ARGS 2 /* ArgFunction */
#define NTP_UNKNOWN 3 /* CommentFunction */
struct NameList {
struct ShortList List;
ULONG Type; /* set by OptimizeFDData */
STRPTR NormName;
STRPTR PragName;
};
struct InOut {
ULONG file;
STRPTR pos;
STRPTR buf;
ULONG size;
};
/* EHF definitions! */
#define HUNK_PPC_CODE 0x4E9
#define HUNK_RELRELOC26 0x4EC
#define EXT_RELREF26 229
/* ------------------------------------------------------------------ */
/* A short set of ELF definitions, see pasm sources in vbcc release for an
more complete set of stuff or get elf documentation. These are needed for
VBCCPUPCode function. */
#define ELFCLASS32 1
#define ELFDATA2MSB 2
#define EV_CURRENT 1 /* version information */
#define ET_REL 1 /* type information */
#define EM_POWERPC 20
#define SHT_NULL 0 /* inactive */
#define SHT_PROGBITS 1 /* program information */
#define SHT_SYMTAB 2 /* symbol table */
#define SHT_STRTAB 3 /* string table */
#define SHT_RELA 4 /* relocation */
#define SHF_ALLOC 0x2 /* needs memory when started */
#define SHF_EXECINSTR 0x4 /* executable instructions */
#define EI_NIDENT 16
#define EI_MAG0 0
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STT_NOTYPE 0
#define STT_SECTION 3
#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
#define ELF32_R_INFO(s,t) (((s)<<8)+(UBYTE)(t))
#define R_PPC_ADDR16_LO 4
#define R_PPC_ADDR16_HA 6
#define R_PPC_REL24 10
#define R_PPC_SDAREL16 32
struct Elf32_Ehdr {
UBYTE e_ident[EI_NIDENT];
UWORD e_type;
UWORD e_machine;
ULONG e_version;
ULONG e_entry;
ULONG e_phoff;
ULONG e_shoff;
ULONG e_flags;
UWORD e_ehsize;
UWORD e_phentsize;
UWORD e_phnum;
UWORD e_shentsize;
UWORD e_shnum;
UWORD e_shstrndx;
};
struct Elf32_Shdr {
ULONG sh_name;
ULONG sh_type;
ULONG sh_flags;
APTR sh_addr;
ULONG sh_offset;
ULONG sh_size;
ULONG sh_link;
ULONG sh_info;
ULONG sh_addralign;
ULONG sh_entsize;
};
struct Elf32_Rela {
ULONG r_offset;
ULONG r_info;
ULONG r_addend;
};
struct Elf32_Sym {
ULONG st_name;
ULONG st_value;
ULONG st_size;
UBYTE st_info;
UBYTE st_other;
UWORD st_shndx;
};
struct ArHeader {
UBYTE ar_name[16]; /* name */
UBYTE ar_time[12]; /* modification time */
UBYTE ar_uid[6]; /* user id */
UBYTE ar_gid[6]; /* group id */
UBYTE ar_mode[8]; /* octal file permissions */
UBYTE ar_size[10]; /* size in bytes */
UBYTE ar_fmag[2]; /* consistency check */
};
/* ------------------------------------------------------------------ */
struct RememberMem { /* structure for selfmade global memory list */
struct RememberMem * rm_Next; /* pointer to next entry */
ULONG rm_Size; /* entry size */
};
struct RDArgs * rda = 0;
struct InOut in = {0,0,0,0},
out = {0,0,0,5120};
struct ClibData * clibdata = 0;
struct FileInfoBlock * fib = 0;
struct ShortListRoot AmiPragma = {0,0,sizeof(struct AmiPragma)},
Comment = {0,0,sizeof(struct Comment)};
struct RememberMem * remember = 0;
APTR mempool = 0;
struct CPP_ExternNames *extnames = 0;
ULONG oldfh = 0;
ULONG lock = 0;
STRPTR BaseName = 0; /* the correct basename */
STRPTR ShortBaseName = 0; /* the filename part of basename without Base */
STRPTR ShortBaseNameUpper = 0; /* like ShortBaseName, but upper case */
ULONG DosVersion = 37; /* force OS2.0 */
STRPTR HEADER = 0;
APTR tempbuf = 0;
ULONG headersize = 0;
ULONG Flags = 0;
ULONG Output_Error = 1; /* Output error occured when 0 */
ULONG tagfuncs = 0; /* are there some tagfuncs in FD */
/* Prototypes for the functions */
STRPTR DupString(STRPTR, ULONG);
STRPTR AllocListMem(ULONG);
STRPTR SkipBlanks(STRPTR);
STRPTR SkipBlanksRet(STRPTR);
STRPTR SkipName(STRPTR);
STRPTR GetBaseType(void);
ULONG CloseDest(STRPTR);
ULONG MakeTagFunction(struct AmiPragma *);
void MakeLines(STRPTR, ULONG);
ULONG SpecialFuncs(void);
void SortFDList(void);
ULONG ScanFDFile(void);
LONG ScanTypes(STRPTR, ULONG);
void FindHeader(void);
ULONG GetRegisterData(struct AmiPragma *);
UWORD GetFRegisterData(struct AmiPragma *);
ULONG OutputXDEF(STRPTR, ...);
ULONG OutputSYMBOL(STRPTR, ...);
UWORD *AsmStackCopy(UWORD *, struct AmiPragma *, ULONG, ULONG);
/* ------------------------------------------------------------------ */
void DoError(UBYTE, ULONG, ...);
ULONG CheckError(struct AmiPragma *, ULONG);
ULONG Out(ULONG);
ULONG DoOutput(STRPTR, ...);
ULONG DoOutputDirect(APTR, ULONG);
/* ------------------------------------------------------------------ */
struct ShortList *NewItem(struct ShortListRoot *);
struct ShortList *RemoveItem(struct ShortListRoot *, struct ShortList *);
void AddItem(struct ShortListRoot *, struct ShortList *);
/* ------------------------------------------------------------------ */
typedef ULONG (*FuncType)(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncAMICALL(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncLIBCALL(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncAsmText(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncAsmCode(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncCSTUBS (struct AmiPragma *, ULONG, STRPTR);
ULONG FuncLVOXDEF(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncLVO (struct AmiPragma *, ULONG, STRPTR);
ULONG FuncLVOLib (struct AmiPragma *, ULONG, STRPTR);
ULONG FuncLocCode(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncLocText(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncInline (struct AmiPragma *, ULONG, STRPTR);
ULONG FuncPowerUP(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncFPCUnit(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncFPCType(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncBMAP (struct AmiPragma *, ULONG, STRPTR);
ULONG FuncVBCCInline (struct AmiPragma *, ULONG, STRPTR);
ULONG FuncVBCCWOSText(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncVBCCWOSCode(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncVBCCPUPText(struct AmiPragma *, ULONG, STRPTR);
ULONG FuncVBCCPUPCode(struct AmiPragma *, ULONG, STRPTR);
ULONG CallFunc(ULONG, STRPTR, FuncType);
/* ------------------------------------------------------------------ */
LONG AddClibEntry(STRPTR, STRPTR, ULONG);
LONG ScanClibFile(STRPTR, STRPTR);
LONG IsCPPType(struct CPP_NameType *, UBYTE);
LONG GetCPPType(struct CPP_NameType *, STRPTR);
struct ClibData *GetClibFunc(STRPTR, struct AmiPragma *, ULONG);
LONG CheckKeyword(STRPTR, STRPTR, LONG);
ULONG CopyCPPType(STRPTR, ULONG, struct ClibData *, struct AmiArgs *);
ULONG OutClibType(struct CPP_NameType *, STRPTR);
ULONG OutPASCALType(struct CPP_NameType *, STRPTR, ULONG);
/* ------------------------------------------------------------------ */
ULONG CallPrag(ULONG, STRPTR, FuncType);
ULONG CreatePragmaFile(STRPTR, STRPTR, STRPTR, STRPTR, ULONG);
ULONG CreateCSTUBSFile(void);
ULONG CreateLVOFile(ULONG);
ULONG CreateAsmStubs(ULONG, ULONG);
ULONG CreateProtoFile(ULONG);
ULONG CreateLocalData(STRPTR, ULONG, STRPTR, ULONG);
ULONG CreateInline(ULONG, ULONG);
ULONG CreateSASPowerUP(ULONG);
ULONG CreateProtoPowerUP(void);
ULONG CreateFPCUnit(void);
ULONG CreateBMAP(void);
ULONG CreateVBCCInline(void);
ULONG CreateVBCC(ULONG, ULONG);
ULONG CreateVBCCPUPCode(ULONG);
/* ------------------------------------------------------------------ */
ULONG GetName(struct NameList *, struct ShortListRoot *, ULONG);
ULONG MakeFD(struct PragList *);
void OptimizeFDData(struct PragData *);
UBYTE GetHexValue(UBYTE);
UBYTE GetDoubleHexValue(UBYTE *);
ULONG AddFDData(struct ShortListRoot *, struct FDData *);
ULONG GetLibData(struct FDData *);
ULONG GetFlibData(struct FDData *);
ULONG GetAmiData(struct FDData *);
ULONG CreateFDFile(STRPTR);
/* ------------------------------------------------------------------ */
void main(void);
void End(ULONG);
enum {
ERR_TAGFUNC_NEEDS_ARGUMENT,
ERR_CANNOT_CONVERT_PRAGMA_TAGCALL,
ERR_TAG_DEF_WITHOUT_PRAGMA,
ERR_BASENAME_DECLARED_TWICE,
ERR_EXPECTED_SLASH_IN_BASENAME,
ERR_EXPECTED_BASENAME,
ERR_EXPECTED_BIAS_VALUE,
ERR_ASSUMING_POSITIVE_BIAS_VALUE,
ERR_MISSING_FUNCTION_NAME,
ERR_EXPECTED_OPEN_BRACKET,
ERR_TO_MUCH_ARGUMENTS,
ERR_EXPECTED_ARGUMENT_NAME,
ERR_EXPECTED_CLOSE_BRACKET,
ERR_EXPECTED_REGISTER_NAME,
ERR_A7_NOT_ALLOWED,
ERR_REGISTER_USED_TWICE,
ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER,
ERR_ASSUMING_BIAS_OF_30,
ERR_EXTRA_CHARACTERS,
ERR_MISSING_BASENAME,
ERR_WRITING_FILE,
ERR_EXPECTED_COMMA,
ERR_DIFFERENT_TO_PREVIOUS,
ERR_UNKNOWN_VARIABLE_TYPE,
ERR_UNKNOWN_ERROR,
ERR_MISSING_END,
ERR_PROTOTYPE_MISSING,
ERR_NOPROTOTYPES_FILE,
ERR_UNKNOWN_DIRECTIVE,
ERR_INLINE_A4_AND_A5,
ERR_INLINE_D7_AND_A45,
ERR_MISSING_SHORTBASENAME,
ERR_USER_ABORT,
ERR_A6_NOT_ALLOWED,
ERR_EMPTY_FILE,
ERR_FLOATARG_NOT_ALLOWED,
ERR_WRONG_TYPES_LINE,
ERR_LONG_DOUBLE,
ERR_CLIB_ARG_COUNT,
ERR_OPEN_FILE,
ERR_A5_NOT_ALLOWED,
ERR_PPC_FUNCTION_NOT_SUPPORTED,
ERR_UNKNOWN_ABI,
};
const struct ErrField {
UBYTE Type; /* 0 = Error, 1 = Warning */
UBYTE Skip;
STRPTR Error;
} Errors[] = {
{1, 1, "Tag function must have arguments."},
{1, 1, "Cannot convert pragma name into tag name."},
{1, 1, "Tag definition without preceding Pragma."},
{1, 0, "Basename declared twice."},
{1, 0, "Expected preceding _ in Basename."},
{1, 1, "Expected Basename."},
{1, 0, "Expected Bias value."},
{1, 0, "Assuming positive bias value."},
{1, 1, "Missing function name."},
{1, 1, "Expected '('."},
{1, 1, "Too much arguments."},
{1, 1, "Expected argument name."},
{1, 1, "Expected ')'."},
{1, 1, "Expected register name."},
{1, 1, "A7 not allowed as argument register."},
{1, 1, "Register used twice."},
{1, 0, "Number of arguments != number of registers."},
{1, 0, "Assuming bias of 30."},
{1, 1, "Extra characters."},
{0, 0, "Missing Basename in FD file."},
{0, 0, "Failed to write destination file."},
{1, 1, "Expected ','."},
{0, 1, "Data different to previous given."},
{1, 0, "Unknown type of argument %ld."},
{0, 0, "Unknown problem: program error or corrupt input data."},
{1, 0, "Missing ##end."},
{1, 0, "Prototype for function \"%s\" not found."},
{0, 0, "No prototypes file (CLIB parameter) was specified."},
{1, 1, "Unknown directive '##%s' found."},
{1, 0, "Usage of both A4 and A5 is not supported."},
{1, 0, "Usage of both D7 and A4 or A5 is not supported."},
{0, 0, "Missing Basename in FD file and FD filename."},
{0, 0, "User aborted operation."},
{1, 0, "A6 not allowed as argument register."},
{1, 0, "Empty or partial file deleted."},
{1, 1, "Floating point arguments not allowed."},
{0, 0, "Wrong definition in external type definition file."},
{1, 0, "Cannot determine if FPU argument is double or single."},
{1, 0, "CLIB argument count differs for %s (%ld != %ld)."},
{0, 0, "Could not open file \"%s\"."},
{1, 0, "A5 cannot be used as argument register."},
{1, 0, "Format supports no PPC functions."},
{1, 0, "Unknown ABI '%s' found."},
};
const struct CPP_TypeField CPP_Field[] = {
{"long", 4, 0, CPP_TYPE_LONG},
{"LONG", 4, 0, CPP_TYPE_LONG},
{"BPTR", 4, 0, CPP_TYPE_LONG},
{"BSTR", 4, 0, CPP_TYPE_LONG},
{"CxObj", 5, 0, CPP_TYPE_LONG},
{"CxMsg", 5, 0, CPP_TYPE_LONG},
{"ULONG", 5, CPP_FLAG_UNSIGNED, CPP_TYPE_LONG},
{"LONGBITS", 8, CPP_FLAG_UNSIGNED, CPP_TYPE_LONG},
{"CPTR", 4, CPP_FLAG_UNSIGNED, CPP_TYPE_LONG},
{"Tag", 3, CPP_FLAG_UNSIGNED, CPP_TYPE_LONG},
{"Object", 6, CPP_FLAG_UNSIGNED, CPP_TYPE_LONG},
{"short", 5, 0, CPP_TYPE_WORD},
{"SHORT", 5, 0, CPP_TYPE_WORD},
{"COUNT", 5, 0, CPP_TYPE_WORD},
{"WORD", 4, 0, CPP_TYPE_WORD},
{"USHORT", 6, CPP_FLAG_UNSIGNED, CPP_TYPE_WORD},
{"UWORD", 5, CPP_FLAG_UNSIGNED, CPP_TYPE_WORD},
{"UCOUNT", 6, CPP_FLAG_UNSIGNED, CPP_TYPE_WORD},
{"WORDBITS", 8, CPP_FLAG_UNSIGNED, CPP_TYPE_WORD},
{"RPTR", 4, CPP_FLAG_UNSIGNED, CPP_TYPE_WORD},
{"BOOL", 4, CPP_FLAG_BOOLEAN, CPP_TYPE_WORD},
{"char", 4, 0, CPP_TYPE_BYTE},
{"BYTE", 4, 0, CPP_TYPE_BYTE},
{"UBYTE", 5, CPP_FLAG_UNSIGNED, CPP_TYPE_BYTE},
{"TEXT", 4, CPP_FLAG_UNSIGNED, CPP_TYPE_BYTE},
{"BYTEBITS", 8, CPP_FLAG_UNSIGNED, CPP_TYPE_BYTE},
{"float", 5, 0, CPP_TYPE_FLOAT},
{"FLOAT", 5, 0, CPP_TYPE_FLOAT},
{"double", 6, 0, CPP_TYPE_DOUBLE},
{"DOUBLE", 6, 0, CPP_TYPE_DOUBLE},
{"void", 4, 0, CPP_TYPE_VOID},
{"VOID", 4, 0, CPP_TYPE_VOID},
{"APTR", 4, CPP_FLAG_POINTER, CPP_TYPE_VOID},
{"STRPTR", 6, CPP_FLAG_POINTER|CPP_FLAG_STRPTR|CPP_FLAG_UNSIGNED, CPP_TYPE_BYTE},
{"CONST_STRPTR",12,CPP_FLAG_POINTER|CPP_FLAG_CONST, CPP_TYPE_BYTE},
{"ClassID", 7, CPP_FLAG_POINTER|CPP_FLAG_UNSIGNED, CPP_TYPE_BYTE},
{"PLANEPTR", 8, CPP_FLAG_POINTER|CPP_FLAG_UNSIGNED, CPP_TYPE_BYTE},
{0,0,0,0},
};
const struct Proto_LibType Proto_LibTypes[] = {
{"DOSBase", "DosLibrary"},
{"SysBase", "ExecBase"},
{"ExpansionBase", "ExpansionBase"},
{"GfxBase", "GfxBase"},
{"IntuitionBase", "IntuitionBase"},
{"LocaleBase", "LocaleBase"},
{"MathIeeeDoubBasBase", "MathIEEEBase"},
{"MathIeeeDoubTransBase", "MathIEEEBase"},
{"MathIeeeSingBasBase", "MathIEEEBase"},
{"MathIeeeSingTransBase", "MathIEEEBase"},
{"RealTimeBase", "RealTimeBase"},
{"RexxSysBase", "RxsLib"},
{"UtilityBase", "UtilityBase"},
/* resources - The Node entries may be correct, but I don't know it. */
/* {"BattClockBase", "Node"}, */
/* {"BattMemBase", "Node"}, */
{"DiskBase", "DiskResource"},
/* {"MiscBase", "Node"}, */
/* {"PotgoBase", "Node"}, */
/* devices */
{"ConsoleDevice", "Device"},
{"InputBase", "Device"},
{"RamdriveDevice", "Device"},
{"TimerBase", "Device"},
/* non default Basenames */
{"DatamasterBase", "DatamasterBase"},
{"PPBase", "PPBase"},
{"ReqToolsBase", "ReqToolsBase"},
{"UnpackBase", "UnpackLibrary"},
{"xfdMasterBase", "xfdMasterBase"},
{"xadMasterBase", "xadMasterBase"},
{"xvsBase", "xvsBase"},
{"GTXBase", "GTXBase"},
{"ArpBase", "ArpBase"},
{0, 0},
};
/* CachePostDMA, CachePreDMA are done by #?DMA check */
const struct Pragma_ExecpName Pragma_ExecpNames[] = {
{"VFWritef", "FWritef"},
{"VFPrintf", "FPrintf"},
{"VPrintf", "Printf"},
{"ReadArgs", 0},
{"FreeArgs", 0},
{"CloneTagItems", 0},
{"FindTagItem", 0},
{"FreeTagItems", 0},
{"GetTagData", 0},
{"PackBoolTags", 0},
{"PackStructureTags", 0},
{"UnpackStructureTags", 0},
{"BGUI_PackStructureTags", 0},
{"BGUI_UnpackStructureTags", 0},
{0,0},
};
/* For double tagcall names (currently only necessary for dos.library and
datatypes.library). Only one alias supported for a function! */
const struct Pragma_AliasName Pragma_AliasNames[] = {
{"AllocDosObject", "AllocDosObjectTagList", FUNCFLAG_NORMAL},
{"CreateNewProc", "CreateNewProcTagList", FUNCFLAG_NORMAL},
{"NewLoadSeg", "NewLoadSegTagList", FUNCFLAG_NORMAL},
{"SystemTagList", "System", FUNCFLAG_NORMAL},
{"RefreshDTObject", "RefreshDTObjects", FUNCFLAG_TAG},
{0,0,0},
};
/* special names, which get an x before name in BMAP files */
const STRPTR BMAPSpecial[] =
{"abs", "Close", "Exit", "Input", "Open", "Output", "Read", "tan",
"Translate", "Wait", "Write", 0};
STRPTR DupString(STRPTR Str, ULONG Len)
{
STRPTR res;
if((res = AllocListMem(Len+1)))
{
CopyMem(Str, res, Len);
res[Len] = '\0';
}
return res;
}
STRPTR AllocListMem(ULONG size)
{
if(mempool) /* mempool exists only for OS39 and up */
return (STRPTR) AllocPooled(mempool, size);
else /* else use linked list */
{
struct RememberMem *r;
size += sizeof(struct RememberMem);
if((r = (struct RememberMem *) AllocMem(size, MEMF_ANY|MEMF_CLEAR)))
{
r->rm_Next = remember;
r->rm_Size = size;
remember = r;
return ((STRPTR) r)+sizeof(struct RememberMem);
}
return 0;
}
}
STRPTR SkipBlanks(STRPTR OldPtr)
{
while(*OldPtr == ' ' || *OldPtr == '\t')
++OldPtr;
return OldPtr;
}
STRPTR SkipBlanksRet(STRPTR OldPtr)
{
while(*OldPtr == ' ' || *OldPtr == '\t' || *OldPtr == '\n')
++OldPtr;
return OldPtr;
}
/*
This function is used to skip over variable names.
Inputs: OldPtr - pointer to the beginning of a string.
Result: Pointer to the first character of the string, that is not one
of a-z, A-Z, 0-9 or the underscore.
*/
STRPTR SkipName(STRPTR OldPtr)
{
while(isalnum(*OldPtr) || *OldPtr == '_')
++OldPtr;
return OldPtr;
}
STRPTR GetBaseType(void)
{
ULONG i;
STRPTR str = "Library";
for(i = 0; BaseName && Proto_LibTypes[i].BaseName; ++i)
{
if(!(strcmp(Proto_LibTypes[i].BaseName, BaseName)))
{
str = Proto_LibTypes[i].StructureName; break;
}
}
return str;
}
ULONG CloseDest(STRPTR name)
{
if(out.file)
{
Out(out.size); /* clears Output-Buffer */
Close(out.file);
out.file = 0;
if(!(Flags & FLAG_DONE) || !Output_Error || CTRL_C)
{
DoError(ERR_EMPTY_FILE, 0);
DeleteFile(name); return 0;
}
Flags &= ~FLAG_DONE; /* clear the flag */
}
else
return 0;
return 1;
}
ULONG MakeTagFunction(struct AmiPragma *ap)
{
ULONG len = strlen(ap->FuncName), i=0;
#ifdef DEBUG_OLD
VPrintf("MakeTagFunction:\n", 0);
#endif
if(!ap->NumArgs)
return 1;
++tagfuncs;
while(Pragma_ExecpNames[i].FunctionName && /* check the exception names */
strcmp(ap->FuncName, Pragma_ExecpNames[i].FunctionName))
++i;
if(Pragma_ExecpNames[i].FunctionName)
{
if(!(ap->TagName = Pragma_ExecpNames[i].TagName));
--tagfuncs;
}
else if(ap->FuncName[len-1] == 'A')
{
if(!strcmp(ap->FuncName+len-3, "DMA") ||
!strcmp(ap->FuncName+len-4, "MESA")) /* skip names with DMA or MESA at end */
{ --tagfuncs; return 1;}
if(!(ap->TagName = DupString(ap->FuncName, len-1)))
return 0;
}
else if(!strcmp(ap->FuncName + len-7, "TagList"))
{
if(!(ap->TagName = DupString(ap->FuncName, len-3)))
return 0;
ap->TagName[len-4] = 's';
}
else if(!strcmp(ap->FuncName + len-4, "Args"))
{
if(!(ap->TagName = DupString(ap->FuncName, len-4)))
return 0;
}
else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "tags") ||
!stricmp(ap->Args[ap->NumArgs-1].ArgName, "taglist"))
{
if(!(ap->TagName = DupString(ap->FuncName, len+4)))
return 0;
CopyMem("Tags", ap->TagName + len, 5);
}
else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "args"))
{
if(!(ap->TagName = DupString(ap->FuncName, len+4)))
return 0;
CopyMem("Args", ap->TagName + len, 5);
}
else
--tagfuncs; /* not a tagfunction, incrementing was false, undo it */
return 1;
}
void MakeLines(STRPTR buffer, ULONG size)
{
if(size && buffer)
{
/* make a real C++ zero string ending line */
while(--size)
{
if(*buffer == '\n')
*buffer = '\0';
++buffer;
}
*buffer = '\0';
}
}
/* Do any special functions, which cannot be done with other exception
stuff - currently only dos.library DoPkt function. */
ULONG SpecialFuncs(void)
{
struct AmiPragma *ap = (struct AmiPragma *) AmiPragma.Last;
if(ap->Bias == 0xF0 && !strcmp("DoPkt", ap->FuncName))
{
struct AmiPragma *d;
ULONG i;
for(i = 0; i < 5; ++i)
{
if(!(d = (struct AmiPragma *) NewItem(&AmiPragma)))
return 0;
CopyMem(ap, d, sizeof(struct AmiPragma));
d->FuncName = DupString(ap->FuncName, 6);
d->FuncName[5] = '0'+i;
d->NumArgs = d->CallArgs = i + 2;
AddItem(&AmiPragma, (struct ShortList *) d);
}
}
return 1;
}
void SortFDList(void)
{
struct AmiPragma *ap = (struct AmiPragma *) AmiPragma.First, *ap2, *ap3;
AmiPragma.First = AmiPragma.Last = 0;
while(ap)
{
ap3 = 0;
ap2 = (struct AmiPragma *) AmiPragma.First;
/* for FD2Inline style we need to use strcmp instead of stricmp here */
while(ap2 && stricmp(ap2->FuncName, ap->FuncName) < 0)
{
ap3 = ap2;
ap2 = (struct AmiPragma *) ap2->List.Next;
}
ap2 = ap;
ap = (struct AmiPragma *) ap->List.Next;
if(ap3)
{
ap2->List.Next = (struct ShortList *) ap3->List.Next;
ap3->List.Next = (struct ShortList *) ap2;
}
else
{
ap2->List.Next = AmiPragma.First;
AmiPragma.First = (struct ShortList *) ap2;
}
if(ap && !ap->List.Next)
AmiPragma.Last = (struct ShortList *) ap2;
}
}
ULONG ScanFDFile(void)
{
#ifdef DEBUG_OLD
VPrintf("ScanFDFile:\n", 0);
#endif
ULONG _public = 1;
LONG bias = -1;
ULONG linenum, len;
ULONG actcom = 0;
ULONG abi = ABI_M68K;
for(linenum = 1; !CTRL_C && in.pos < in.buf + in.size; ++linenum)
{
if(*in.pos == '*') /* Comment */
{
STRPTR oldpos = in.pos;
#ifdef DEBUG_OLD
VPrintf("ScanFDFile: found a comment\n", 0);
#endif
in.pos = SkipBlanks(in.pos+1);
if(!strnicmp(in.pos, "notagcall", 9))
{
struct AmiPragma *ap = (struct AmiPragma *) AmiPragma.Last;
if(ap->TagName)
{
--tagfuncs; ap->TagName = 0;
}
in.pos = SkipBlanks(in.pos + 9);
}
else if(!strnicmp(in.pos, "tagcall", 7)) /* Tag to create? */
{
struct AmiPragma *prevpragma = (struct AmiPragma *) AmiPragma.Last;
in.pos = SkipBlanks(in.pos + 7);
if(!prevpragma)
{
DoError(ERR_TAG_DEF_WITHOUT_PRAGMA, linenum);
++in.pos;
continue;
}
if(!prevpragma->NumArgs)
{
DoError(ERR_TAGFUNC_NEEDS_ARGUMENT, linenum);
++in.pos;
continue;
}
/* Get the tag functions name. */
if(!prevpragma->TagName && (_public || (Flags & FLAG_PRIVATE)))
++tagfuncs;
if(*in.pos)
{
STRPTR oldptr, tptr = prevpragma->TagName;
len = strlen(prevpragma->FuncName)+strlen(in.pos)+1;
if(!(prevpragma->TagName = DupString(prevpragma->FuncName, len)))
return 0;
if(*in.pos == '-')
{
STRPTR removeptr;
oldptr = in.pos = SkipBlanks(in.pos+1);
in.pos = SkipName(in.pos);
if((len = in.pos-oldptr))
{
removeptr = prevpragma->TagName+strlen(prevpragma->TagName)-len;
if(strncmp(removeptr, oldptr, len))
{
#ifdef DEBUG_OLD
{
struct data {STRPTR a;STRPTR b;ULONG c;} a;
a.a = removeptr;
a.b = oldptr;
a.c = len;
VPrintf("ScanFDFile: *tagcall -: %s, %s, %ld\n", &a);
}
#endif
DoError(ERR_CANNOT_CONVERT_PRAGMA_TAGCALL, linenum);
prevpragma->TagName = tptr;
++in.pos;
continue;
}
*removeptr = '\0';
}
in.pos = SkipBlanks(in.pos);
}
if(*in.pos == '+')
in.pos = SkipBlanks(in.pos+1);
else
*in.pos = toupper(*in.pos);
in.pos = SkipName((oldptr = in.pos));
len = in.pos-oldptr;
if(len)
{
ULONG a = strlen(prevpragma->TagName);
CopyMem(oldptr, prevpragma->TagName+a, len);
prevpragma->TagName[a+len] = '\0';
}
}
else if(!prevpragma->TagName)
{
len = strlen(prevpragma->FuncName);
if(!(prevpragma->TagName = DupString(prevpragma->FuncName, len+4)))
return 0;
CopyMem("Tags", prevpragma->TagName + len, 5);
}
}
else
{
if(actcom)
*(oldpos-1) = '\n';
else if(Flags & FLAG_DOCOMMENT)
{
struct Comment *d;
if(!(d = (struct Comment *) NewItem(&Comment)))
return 0;
d->Bias = bias;
d->Data = oldpos;
AddItem(&Comment, (struct ShortList *) d);
actcom = 1;
}
while(*in.pos)
++in.pos;
}
}
else if(*in.pos == '#' && in.pos[1] == '#')
{
in.pos += 2;
actcom = 0; /* no Comment */
if(!strnicmp(in.pos, "base", 4))
{
#ifdef DEBUG_OLD
VPrintf("ScanFDFile: found ##base\n", 0);
#endif
STRPTR oldptr;
if(BaseName)
DoError(ERR_BASENAME_DECLARED_TWICE, linenum);
in.pos = SkipBlanks(in.pos+4);
if(*in.pos != '_')
DoError(ERR_EXPECTED_SLASH_IN_BASENAME, linenum);
else
++in.pos;
in.pos = SkipName((oldptr = in.pos));
if((len = in.pos-oldptr))
{
if(!(BaseName = DupString(oldptr, len)))
return 0;
if(!ShortBaseName && !(ShortBaseName = DupString(BaseName, len-4)))
return 0;
}
else
DoError(ERR_EXPECTED_BASENAME, linenum);
}
else if(!strnicmp(in.pos, "bias", 4))
{
#ifdef DEBUG_OLD
VPrintf("ScanFDFile: found ##bias\n", 0);
#endif
STRPTR ptr;
LONG newbias;
in.pos += 5;
newbias = strtol(in.pos, &ptr, 10);
if(ptr == in.pos)
DoError(ERR_EXPECTED_BIAS_VALUE, linenum);
else if(newbias < 0)
{
DoError(ERR_ASSUMING_POSITIVE_BIAS_VALUE, linenum);
bias = -newbias;
}
else
bias = newbias;
in.pos = SkipName(in.pos);
}
else if(!strnicmp(in.pos, "end", 3))
{
bias = 0; break;
}
else if(!strnicmp(in.pos, "shadow", 6)) /* introduced by Storm */
{
in.pos += 6;
bias -= BIAS_OFFSET;
}
else if(!strnicmp(in.pos, "public", 6))
{
in.pos += 6;
_public = 1;
}
else if(!strnicmp(in.pos, "private", 7))
{
in.pos += 7;
_public = 0;
}
else if(!strnicmp(in.pos, "abi", 3))
{
in.pos = SkipBlanks(in.pos+3);
if(!strnicmp(in.pos, "M68k", 4))
{
abi = ABI_M68K; in.pos += 4;
}
else if(!strnicmp(in.pos, "PPC0", 4))
{
abi = ABI_PPC0; in.pos += 4;
}
else if(!strnicmp(in.pos, "PPC2", 4))
{
abi = ABI_PPC2; in.pos += 4;
}
else if(!strnicmp(in.pos, "PPC", 3))
{
abi = ABI_PPC; in.pos += 3;
}
else
DoError(ERR_UNKNOWN_ABI, linenum, in.pos);
}
else
DoError(ERR_UNKNOWN_DIRECTIVE, linenum, in.pos);
}
else if(abi != ABI_M68K)
{
/*******************************************************/
#ifdef DEBUG
VPrintf("ScanFDFile: scan PPC Function\n", 0);
#endif
STRPTR oldptr;
struct AmiPragma ap;
memset(&ap, 0, sizeof(struct AmiPragma));
actcom = 0;
oldptr = in.pos = SkipBlanks(in.pos);
in.pos = SkipName(oldptr);
if(!(len = in.pos-oldptr))
{
DoError(ERR_MISSING_FUNCTION_NAME, linenum);
++in.pos;
continue;
}
ap.FuncName = oldptr;
in.pos = SkipBlanks(in.pos);
if(*in.pos != '('/*)*/)
{
DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
++in.pos;
continue;
}
*in.pos = '\0'; /* create c string of FunctionName */
#ifdef DEBUG
VPrintf("ScanFDFile: found ppc function %s\n", &ap.FuncName);
#endif
do
{
oldptr = in.pos = SkipBlanks(in.pos+1);
if(*in.pos == /*(*/')' && !ap.CallArgs)
break;
if(ap.CallArgs >= MAXREGPPC)
{
DoError(ERR_TO_MUCH_ARGUMENTS, linenum); break;
}
in.pos = SkipName(oldptr);
if(*in.pos == '*')
++in.pos;
if(!(len = in.pos-oldptr))
{
DoError(ERR_EXPECTED_ARGUMENT_NAME, linenum);
break;
}
ap.Args[ap.CallArgs++].ArgName = oldptr;
oldptr = in.pos;
in.pos = SkipBlanks(in.pos);
if(*in.pos != ',' && *in.pos != '/' && *in.pos != /*(*/')')
{
DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
break;
}
if(*in.pos != /*(*/')') /* create c string ending */
*oldptr = '\0';
} while(*in.pos != /*(*/')');
if(*in.pos != /*(*/')')
{
while(*(in.pos++))
++in.pos;
continue;
}
else
*oldptr = '\0'; /* create c string ending for last argument */
if(*(in.pos = SkipBlanks(in.pos+1)) != '('/*)*/)
{
DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
++in.pos;
continue;
}
if(*(in.pos = SkipBlanks(in.pos+1)) != /*(*/')')
{
DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
++in.pos;
continue;
}
++in.pos;
ap.Bias = bias;
ap.Line = linenum;
ap.NumArgs = ap.CallArgs;
bias += BIAS_OFFSET;
if(bias == -1)
{
DoError(ERR_ASSUMING_BIAS_OF_30, linenum);
bias = 30;
}
if(_public)
ap.Flags |= AMIPRAGFLAG_PUBLIC;
ap.Flags |= AMIPRAGFLAG_PPC;
if(abi == ABI_PPC0)
ap.Flags |= AMIPRAGFLAG_PPC0;
else if(abi == ABI_PPC2)
ap.Flags |= AMIPRAGFLAG_PPC2;
if((_public || (Flags & FLAG_PRIVATE)) && !MakeTagFunction(&ap))
return 0;
else /* check the alias names */
{
ULONG i = 0;
while(Pragma_AliasNames[i].FunctionName &&
strcmp(ap.FuncName, Pragma_AliasNames[i].FunctionName) &&
strcmp(ap.TagName, Pragma_AliasNames[i].FunctionName))
++i;
if(Pragma_AliasNames[i].FunctionName)
ap.AliasName = (struct Pragma_AliasName *) &Pragma_AliasNames[i];
}
if(!(Flags & FLAG_NOPPC))
{
struct AmiPragma *d;
if(!(d = (struct AmiPragma *) NewItem(&AmiPragma)))
return 0;
CopyMem(&ap, d, sizeof(struct AmiPragma));
AddItem(&AmiPragma, (struct ShortList *) d);
/*
if(!SpecialFuncs())
return 0;
*/
}
}
else
{
#ifdef DEBUG_OLD
VPrintf("ScanFDFile: scan Function\n", 0);
#endif
STRPTR oldptr;
struct AmiPragma ap;
memset(&ap, 0, sizeof(struct AmiPragma));
actcom = 0;
oldptr = in.pos = SkipBlanks(in.pos);
in.pos = SkipName(oldptr);
if(!(len = in.pos-oldptr))
{
DoError(ERR_MISSING_FUNCTION_NAME, linenum);
++in.pos;
continue;
}
ap.FuncName = oldptr;
in.pos = SkipBlanks(in.pos);
if(*in.pos != '('/*)*/)
{
DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
++in.pos;
continue;
}
*in.pos = '\0'; /* create c string of FunctionName */
#ifdef DEBUG_OLD
VPrintf("ScanFDFile: found function %s\n", &ap.FuncName);
#endif
do
{
oldptr = in.pos = SkipBlanks(in.pos+1);
if(*in.pos == /*(*/')' && !ap.CallArgs)
break;
if(ap.CallArgs >= MAXREG-2)
{
DoError(ERR_TO_MUCH_ARGUMENTS, linenum); break;
}
in.pos = SkipName(oldptr);
if(*in.pos == '*')
++in.pos;
if(!(len = in.pos-oldptr))
{
DoError(ERR_EXPECTED_ARGUMENT_NAME, linenum);
break;
}
ap.Args[ap.CallArgs++].ArgName = oldptr;
oldptr = in.pos;
in.pos = SkipBlanks(in.pos);
if(*in.pos != ',' && *in.pos != '/' && *in.pos != /*(*/')')
{
DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
break;
}
if(*in.pos != /*(*/')') /* create c string ending */
*oldptr = '\0';
} while(*in.pos != /*(*/')');
if(*in.pos != /*(*/')')
{
while(*(in.pos++))
++in.pos;
continue;
}
else
*oldptr = '\0'; /* create c string ending for last argument */
if(*(in.pos = SkipBlanks(in.pos+1)) != '('/*)*/)
{
DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
++in.pos;
continue;
}
do
{
ULONG i;
oldptr = in.pos = SkipBlanks(in.pos + 1);
if(*in.pos == /*(*/')' && !ap.NumArgs)
break;
in.pos = SkipName(oldptr);
len = in.pos-oldptr;
for(i = 0; i < MAXREG; ++i)
if(!strnicmp(RegNames[i], oldptr, len))
break;
if(i == MAXREG)
{
DoError(ERR_EXPECTED_REGISTER_NAME, linenum);
break;
}
else if(i == REG_A6)
ap.Flags |= AMIPRAGFLAG_A6USE;
else if(i == REG_A5)
ap.Flags |= AMIPRAGFLAG_A5USE;
else if(i == REG_A4)
ap.Flags |= AMIPRAGFLAG_A4USE;
else if(i == REG_D7)
ap.Flags |= AMIPRAGFLAG_D7USE;
else if(i == REG_A7)
{
DoError(ERR_A7_NOT_ALLOWED, linenum);
break;
}
else if(i >= REG_FP0)
ap.Flags |= AMIPRAGFLAG_FLOATARG;
ap.Args[ap.NumArgs].ArgReg = i;
if(ap.CallArgs < ap.NumArgs) /* get name when no given */
ap.Args[ap.NumArgs].ArgName = RegNames[i];
for(i = 0; i < ap.NumArgs; i++)
{
if(ap.Args[ap.NumArgs].ArgReg == ap.Args[i].ArgReg)
{
DoError(ERR_REGISTER_USED_TWICE, linenum);
break;
}
}
if(i < ap.NumArgs)
break;
++ap.NumArgs;
in.pos = SkipBlanks(in.pos);
if(*in.pos != ',' && *in.pos != '/' && *in.pos != /*(*/')')
{
DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
break;
}
} while(*in.pos != /*(*/')');
ap.Bias = bias;
ap.Line = linenum;
bias += BIAS_OFFSET;
if(*in.pos != /*(*/')')
{
while(*(in.pos++))
++in.pos;
continue;
}
else
++in.pos;
if(Flags & FLAG_STORMFD)
{
if(!strcmp(ap.Args[ap.CallArgs-1].ArgName, "tags"))
{
ap.TagName = ap.FuncName;
ap.FuncName = 0;
++tagfuncs;
#ifdef DEBUG_OLD
VPrintf("ScanFDFile: StormFD mode, tag func: %s\n", &ap.TagName);
#endif
}
#ifdef DEBUG_OLD
else
{
STRPTR a[2];
a[0] = ap.FuncName;
a[1] = ap.Args[ap.CallArgs-1].ArgName;
VPrintf("ScanFDFile: StormFD mode, normal func: %s(..., %s)\n", &a);
}
#endif
}
else if((_public || (Flags & FLAG_PRIVATE)) && !MakeTagFunction(&ap))
return 0;
else /* check the alias names */
{
ULONG i = 0;
while(Pragma_AliasNames[i].FunctionName &&
strcmp(ap.FuncName, Pragma_AliasNames[i].FunctionName) &&
strcmp(ap.TagName, Pragma_AliasNames[i].FunctionName))
++i;
if(Pragma_AliasNames[i].FunctionName)
ap.AliasName = (struct Pragma_AliasName *) &Pragma_AliasNames[i];
}
if(ap.CallArgs != ap.NumArgs)
ap.Flags |= AMIPRAGFLAG_ARGCOUNT;
if(bias == -1)
{
DoError(ERR_ASSUMING_BIAS_OF_30, linenum);
bias = 30;
}
if(_public)
ap.Flags |= AMIPRAGFLAG_PUBLIC;
if((Flags & FLAG_NOFPU) && (ap.Flags & AMIPRAGFLAG_FLOATARG))
DoError(ERR_FLOATARG_NOT_ALLOWED, linenum);
else if(((ap.Flags & AMIPRAGFLAG_FLOATARG) || !(Flags & FLAG_FPUONLY))
&& !(Flags & FLAG_PPCONLY))
{ /* skip all without FPU when FPUONLY and PPC when PPCONLY */
struct AmiPragma *d;
if(!(d = (struct AmiPragma *) NewItem(&AmiPragma)))
return 0;
CopyMem(&ap, d, sizeof(struct AmiPragma));
AddItem(&AmiPragma, (struct ShortList *) d);
if(!SpecialFuncs())
return 0;
}
}
in.pos = SkipBlanks(in.pos);
if(*in.pos)
DoError(ERR_EXTRA_CHARACTERS, linenum);
++in.pos; /* skip '\0' */
}
if(CTRL_C)
{
DoError(ERR_USER_ABORT, 0);
return 0;
}
if(bias)
DoError(ERR_MISSING_END, 0);
return 1;
}
LONG ScanTypes(STRPTR ptr, ULONG size)
{
struct CPP_ExternNames *a = 0, *b = 0;
STRPTR endptr = ptr+size;
LONG line;
for(line = 1; ptr < endptr; ++line)
{
struct CPP_ExternNames *n;
if(*ptr == '*') /* skip comments */
{
while(ptr < endptr && *(ptr++) != '\n')
;
}
else if((n = (struct CPP_ExternNames *)
AllocListMem(sizeof(struct CPP_ExternNames))))
{
STRPTR wptr;
n->Type = ptr; /* store start */
wptr = ptr;
while(ptr < endptr && *ptr != ':' && *ptr != '\n')
{
if(*ptr == '\t' || *ptr == ' ')
{
*(wptr++) = ' ';
ptr = SkipBlanks(ptr);
}
else
*(wptr++) = *(ptr++);
}
if(*(ptr++) != ':')
return line;
if(*(wptr-1) == ' ')
--wptr;
*wptr = 0;
if(!GetCPPType(&n->NameType, (ptr = SkipBlanks(ptr))))
return line;
#ifdef DEBUG_OLD
Printf("'%20s', slen %2ld, typelen %2ld, pntd %ld, type %lc, sn '%.3s'\n",
n->Type, n->NameType.StructureLength, n->NameType.FullLength,
n->NameType.PointerDepth, n->NameType.Type ? n->NameType.Type : 's',
n->NameType.StructureName ? n->NameType.StructureName : "<e>");
#endif
ptr = SkipBlanks(n->NameType.TypeStart+n->NameType.FullLength);
if(*(ptr++) != '\n')
{
#ifdef DEBUG_OLD
Printf("%.30s\n", ptr);
#endif
return line;
}
if(!a)
b = n;
else
a->Next = n;
a = n;
}
else
return -1;
}
extnames = b; /* now store the list */
return 0;
}
void FindHeader(void)
{
STRPTR str = HEADER;
ULONG mode = 0;
do
{
if(!mode)
HEADER = str;
if(*str == '/')
{
++str;
if(*str == '*')
{
mode = 2; break;
}
else if(*str == '/')
mode = 1;
}
else if(*str == '*' || *str == ';')
mode = 1;
else if(*str == '{'/*}*/)
{
mode = 3; break;
}
else if(*str == '('/*)*/ && *(++str) == '*')
{
mode = 4; break;
}
else if(mode)
break;
while(*str && *(str++) != '\n')
;
} while(*str);
if(mode == 2)
{
while(*str && (*(str-1) != '*' || *str != '/'))
++str;
while(*str && *(str++) != '\n')
;
}
else if(mode == 3)
{
while(*str && *str != /*{*/'}')
++str;
while(*str && *(str++) != '\n')
;
}
else if(mode == 4)
{
while(*str && (*(str-1) != '*' || *str != /*(*/')'))
++str;
while(*str && *(str++) != '\n')
;
}
if(mode)
headersize = str-HEADER;
else
{
HEADER = 0; headersize = 0;
}
}
/* returns decrement data in bits 0-15 and increment data in bits 16-31 */
ULONG GetRegisterData(struct AmiPragma *ap)
{
/* usage of result:
48E7 <lower word> MOVEM.L <registers>,-(A7) ; D0 is bit 15
4CDF <upper word> MOVEM.L (A7)+,<registers> ; D0 is bit 0
*/
register ULONG i, data = 0, reg;
for(i = 0; i < ap->NumArgs; ++i)
{
if((reg = ap->Args[i].ArgReg) <= REG_FP0)
{
if(reg >= 10 || (reg >= 2 && reg <= 7)) /* A2-A7 and D2-D7 */
data |= (1 << (reg + 16)) + (1 << (15 - reg));
}
}
if(data) /* set A6 only when other register used */
data |= 0x40000002;
return data;
}
UWORD GetFRegisterData(struct AmiPragma *ap)
{
/* usage of result:
F227 <upper byte> FMOVEM.X <registers>,-(A7) ; FP0 is bit 0
F21F <lower byte> FMOVEM.X (A7)+,<registers> ; FP0 is bit 7
*/
register ULONG i, reg;
register UWORD data = 0;
for(i = 0; i < ap->NumArgs; ++i)
{
if((reg = ap->Args[i].ArgReg) >= REG_FP2)
{
reg -= REG_FP0;
data |= (1 << (reg + 8)) + (1 << (7 - reg));
}
}
return data;
}
ASM(static void) SAVEDS xdefputfunc(REG(d0, UBYTE data), REG(a3, STRPTR *a))
{
#ifdef __MAXON__
GetBaseReg();
#endif
*((*a)++) = data;
}
ULONG OutputXDEF(STRPTR format, ...)
{
UBYTE b[150];
STRPTR c = b + 4;
UWORD i;
memset(b, 0, 150);
RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
(void(*)()) xdefputfunc, &c);
/* c now holds pointer to end */
i = (c-(b+4)+2)>>2;
*((ULONG *) b) = 0x01000000 + i;
return DoOutputDirect(b, (i+2)<<2);
}
ULONG OutputSYMBOL(STRPTR format, ...)
{
UBYTE b[150];
STRPTR c = b+4;
UWORD i;
memset(b, 0, 150);
RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
(void(*)()) xdefputfunc, &c);
/* c now holds pointer to end */
i = (c-(b+4)+2)>>2;
*((ULONG *) b) = i;
return DoOutputDirect(b, (i+2)<<2);
}
UWORD *AsmStackCopy(UWORD *data, struct AmiPragma *ap, ULONG flags,
ULONG ofs)
{
ULONG j, k;
if(Flags & FLAG_PASCAL)
{
k = ap->NumArgs;
while(k)
{
if(ap->Args[k-1].ArgReg >= REG_FP0)
{
struct ClibData *cd;
cd = GetClibFunc(ap->FuncName, ap, flags);
*(data++) = 0xF22F; /* FMOVE.? offs(A7),FPx */
if(cd && IsCPPType(&cd->Args[k-1], CPP_TYPE_DOUBLE))
{
*(data++) = 0x5400 + ((ap->Args[--k].ArgReg-REG_FP0)<<7);
*(data++) = ofs<<2; /* one double needs two longs */
ofs += 2;
}
else
{
if(!cd || !IsCPPType(&cd->Args[k-1], CPP_TYPE_FLOAT))
DoError(ERR_LONG_DOUBLE, ap->Line);
*(data++) = 0x4400 + ((ap->Args[--k].ArgReg-REG_FP0)<<7);
*(data++) = (ofs++) << 2;
}
}
else if((k >= 2) && (ap->Args[k-1].ArgReg < ap->Args[k-2].ArgReg)
&& ap->Args[k-2].ArgReg < REG_FP0 && !(Flags & FLAG_NOMOVEM))
{
*(data++) = 0x4CEF; /* MOVEM.L offs(A7),xxx */
*(data++) = 0;
*(data++) = ofs << 2; /* store start offset */
do
{
j = ap->Args[--k].ArgReg;
++ofs;
*(data-2) |= 1 << j;
} while(k && j < ap->Args[k-1].ArgReg &&
ap->Args[k-1].ArgReg < REG_FP0);
}
else
{
*data = 0x202F; /* MOVE.L offs(A7),xxx */
if((j = ap->Args[--k].ArgReg) > 7)
{
*data |= (1<<6); j -= 8; /* set MOVEA bit */
}
*(data++) |= j << 9; /* set destination register */
*(data++) = (ofs++) << 2;
}
}
}
else
{
ULONG i = 0;
k = ap->NumArgs - ((flags & FUNCFLAG_TAG) ? 1 : 0);
while(i < k)
{
if(ap->Args[i].ArgReg >= REG_FP0)
{
struct ClibData *cd;
cd = GetClibFunc(ap->FuncName, ap, flags);
*(data++) = 0xF22F; /* FMOVE.? offs(A7),FPx */
if(cd && IsCPPType(&cd->Args[i], CPP_TYPE_DOUBLE))
{
*(data++) = 0x5400 + ((ap->Args[i++].ArgReg-REG_FP0)<<7);
*(data++) = ofs<<2; /* one double needs two longs */
ofs += 2;
}
else
{
if(!cd || !IsCPPType(&cd->Args[i], CPP_TYPE_FLOAT))
DoError(ERR_LONG_DOUBLE, ap->Line);
*(data++) = 0x4400 + ((ap->Args[i++].ArgReg-REG_FP0)<<7);
*(data++) = (ofs++) << 2;
}
}
else if(((k - i) >= 2) && (ap->Args[i].ArgReg < ap->Args[i+1].ArgReg)
&& ap->Args[i+1].ArgReg < REG_FP0 && !(Flags & FLAG_NOMOVEM))
{
*(data++) = 0x4CEF; /* MOVEM.L offs(A7),xxx */
*(data++) = 0; /* Store MOVEM.L data later */
*(data++) = ofs << 2; /* store start offset */
do
{
j = ap->Args[i++].ArgReg;
++ofs;
*(data-2) |= 1 << j;
} while(i < k && j < ap->Args[i].ArgReg &&
ap->Args[i].ArgReg < REG_FP0);
}
else
{
*data = 0x202F; /* MOVE.L offs(A7),xxx */
if((j = ap->Args[i++].ArgReg) > 7)
{
*data |= (1<<6); j -= 8; /* set MOVEA bit */
}
*(data++) |= j << 9; /* set destination register */
*(data++) = (ofs++) << 2;
}
}
if(i < ap->NumArgs)
{
if((j = ap->Args[i].ArgReg) > 7)
{
*(data++) = 0x41EF | ((j-8) << 9); /* LEA xxx(A7),Ax */
*(data++) = ofs << 2;
}
else if(ofs == 2)
{
*(data++) = 0x200F | (j << 9); /* MOVE.L A7,Dx */
*(data++) = 0x5080 | j; /* ADDQ.L #8,Dx */
}
else
{
*(data++) = 0x486F; /* PEA xxx(A7) */
*(data++) = ofs << 2;
*(data++) = 0x201F | j << 9; /* MOVE.L offs(A7),Dx */
}
}
}
return data;
}
/* ------------------------------------------------------------------ */
void DoError(UBYTE errnum, ULONG line, ...)
{
if(Flags & FLAG_DIDERROR)
return;
if(!Errors[errnum].Type)
Flags |= FLAG_DIDERROR;
Printf((line ? "%s %ld in line %ld%s: " : "%s %ld : "), (ULONG)
(Errors[errnum].Type ? "Warning" : "Error"), errnum, line,
errnum == ERR_UNKNOWN_VARIABLE_TYPE ? " of clib file" : "");
VPrintf(Errors[errnum].Error, (((STRPTR) &line) + sizeof(ULONG)));
PutStr("\n");
if(line && Errors[errnum].Skip)
{
while(*in.pos)
++in.pos;
}
}
ULONG CheckError(struct AmiPragma *ap, ULONG errflags)
{
errflags &= ap->Flags;
if(errflags & AMIPRAGFLAG_ARGCOUNT)
{
if(!(ap->Flags & AMIPRAGFLAG_DIDARGWARN))
{
DoError(ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, ap->Line);
ap->Flags |= AMIPRAGFLAG_DIDARGWARN;
}
return 1;
}
else if(errflags & AMIPRAGFLAG_FLOATARG)
{
if(!(ap->Flags & AMIPRAGFLAG_DIDFLOATWARN))
{
DoError(ERR_FLOATARG_NOT_ALLOWED, ap->Line);
ap->Flags |= AMIPRAGFLAG_DIDFLOATWARN;
}
return 1;
}
else if(errflags & AMIPRAGFLAG_A6USE)
{
DoError(ERR_A6_NOT_ALLOWED, ap->Line);
return 1;
}
else if(errflags & AMIPRAGFLAG_A5USE)
{
DoError(ERR_A5_NOT_ALLOWED, ap->Line);
return 1;
}
else if(errflags & AMIPRAGFLAG_PPC)
{
if(!(ap->Flags & AMIPRAGFLAG_DIDPPCWARN))
{
DoError(ERR_PPC_FUNCTION_NOT_SUPPORTED, ap->Line);
ap->Flags |= AMIPRAGFLAG_DIDPPCWARN;
}
return 1;
}
return 0;
}
ULONG Out(ULONG size)
{
ULONG i = out.pos-out.buf;
if(i && out.size - i <= size)
{
if(Write(out.file, out.buf, i) != i)
{
Output_Error = 0;
return 0;
}
out.pos = out.buf;
}
return out.size;
}
ASM(static void) SAVEDS putfunc(REG(d0, UBYTE data), REG(a3, LONG *a))
{
#ifdef __MAXON__
GetBaseReg();
#endif
if(data)
{
if(!*a)
*a = Out(1);
if((*a)-- > 0)
*(out.pos++) = data;
}
}
ULONG DoOutput(STRPTR format, ...)
{
LONG a = out.buf+out.size-out.pos;
if(!Output_Error)
return 0;
RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
(void(*)()) putfunc, &a);
if(a < 0)
return 0;
return 1;
}
ULONG DoOutputDirect(APTR data, ULONG size)
{
if(!Output_Error || !Out(size))
return 0;
CopyMem(data, out.pos, size);
out.pos += size;
return 1;
}
/* ------------------------------------------------------------------ */
struct ShortList *NewItem(struct ShortListRoot *list)
{
struct ShortList *item;
if(!list || !list->Size)
return 0;
if(!(item = (struct ShortList *) AllocListMem(list->Size)))
return 0;
return item;
}
struct ShortList *RemoveItem(struct ShortListRoot *list,
struct ShortList *item)
{
struct ShortList *n = list->First;
if(n == item)
list->First = item->Next;
else
{
while(n && n->Next != item)
n = n->Next;
if(!n)
return 0;
if(!(n->Next = item->Next))
list->Last = n;
}
item->Next = 0;
return item;
}
void AddItem(struct ShortListRoot *list, struct ShortList *item)
{
if(!list->First)
list->First = list->Last = item;
else
{
list->Last->Next = item;
list->Last = item;
}
}
/* ------------------------------------------------------------------ */
ULONG FuncAMICALL(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG i;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
DoOutput("#pragma %s(%s,0x%03lx,%s("/*))*/, flags & FUNCFLAG_TAG ?
"tagcall" : "amicall", BaseName, ap->Bias, name);
for(i = 0; i < ap->NumArgs; ++i)
{
DoOutput(RegNames[ap->Args[i].ArgReg]);
if(i+1 < ap->NumArgs)
DoOutput(",");
}
return DoOutput(/*((*/"))\n");
}
ULONG FuncLIBCALL(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
LONG i;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
if(ap->Flags & AMIPRAGFLAG_FLOATARG)
{
DoOutput("#pragma flibcall %s %-20s %03lx ", BaseName, name, ap->Bias);
for(i = ap->NumArgs-1; i >= 0; --i)
DoOutput("%02lx", ap->Args[i].ArgReg);
return DoOutput("00%02lx\n", ap->NumArgs);
}
if((Flags & FLAG_SYSCALL) && !strcmp(BaseName,"SysBase") &&
(flags & FUNCFLAG_NORMAL))
DoOutput("#pragma syscall %-20s %03lx ", name, ap->Bias);
else
DoOutput("#pragma %s %s %-20s %03lx ", (flags & FUNCFLAG_TAG) ?
"tagcall" : "libcall", BaseName, name, ap->Bias);
for(i = ap->NumArgs-1; i >= 0; --i)
DoOutput("%lx", ap->Args[i].ArgReg);
return DoOutput("0%lx\n", ap->NumArgs);
}
ULONG FuncAsmText(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
LONG i;
ULONG registers;
UWORD fregs;
ULONG offset = 1;
STRPTR c1, c2;
struct ClibData *cd;
if(CheckError(ap, AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
c1 = Flags & FLAG_NEWSYNTAX ? "(" : ""; /*)*/
c2 = Flags & FLAG_NEWSYNTAX ? "," : "("; /*)*/
if(Flags & FLAG_ASMSECTION)
{
DoOutput("\n\tSECTION\t\"%s\",CODE\n\tXREF\t_%s\n", name, BaseName);
}
DoOutput("\n\tXDEF\t_%s\n_%s:\n",name, name);
if(!(Flags & FLAG_PASCAL))
{
DoOutput("\tXDEF\t%s\n%s:\n",name, name);
if(clibdata)
{
if(!ap->NumArgs)
DoOutput("\tXDEF\t%s_\n%s_:\n",name, name);
else if((cd = GetClibFunc(name, ap, flags)))
{
UBYTE txt[300];
ULONG ret = 0;
do
{
if((ret = CopyCPPType(txt, ret, cd, ap->Args)))
DoOutput("\tXDEF\t%s__%s\n%s__%s:\n", name, txt, name, txt);
} while(ret == 0xFFFFFFFF);
}
}
}
if((registers = GetRegisterData(ap) >> 16))
{
if(Flags & FLAG_NOMOVEM)
{
for(i = 0; i <= 15; ++i)
{
if(registers & (1 << i))
{
++offset;
DoOutput("\tMOVE.L\t%s,-(A7)\n", RegNamesUpper[i]);
}
}
}
else
{
UWORD l = registers;
DoOutput("\tMOVEM.L\t");
for(i = 0; i <= 15; ++i)
{
if(l & (1 << i))
{
++offset;
l ^= 1 << i;
DoOutput(RegNamesUpper[i]);
if(l)
DoOutput("/");
}
}
DoOutput(",-(A7)\n");
}
}
else
{
DoOutput("\tMOVE.L\tA6,-(A7)\n"); ++offset;
}
if((fregs = GetFRegisterData(ap) >> 8))
{
UBYTE l = fregs;
DoOutput("\tFMOVEM.X\t");
for(i = 0; i <= 7; ++i)
{
if(l & (1 << i))
{
offset += 3;
l ^= 1 << i;
DoOutput(RegNamesUpper[REG_FP0 + i]);
if(l)
DoOutput("/");
}
}
DoOutput(",-(A7)\n");
}
if(Flags & FLAG_SMALLDATA)
{
DoOutput(/*(*/"\tMOVEA.L\t%s_%s%sA4),A6\n", c1, BaseName, c2);
}
else
DoOutput("\tMOVEA.L\t_%s,A6\n", BaseName);
if(!(Flags & FLAG_PASCAL))
{
ULONG k;
k = ap->NumArgs - ((flags & FUNCFLAG_TAG) ? 1 : 0);
for(i = 0; i < k;)
{
if(ap->Args[i].ArgReg >= REG_FP0)
{
ULONG t;
struct ClibData *cd;
cd = GetClibFunc(name, ap, flags);
if(cd && IsCPPType(&cd->Args[i], CPP_TYPE_DOUBLE))
t = CPP_TYPE_DOUBLE;
else if(cd && IsCPPType(&cd->Args[i], CPP_TYPE_FLOAT))
t = CPP_TYPE_FLOAT;
else
{
DoError(ERR_LONG_DOUBLE, ap->Line);
t = CPP_TYPE_FLOAT;
}
DoOutput(/*(*/"\tFMOVE.%lc\t%s%02ld%sA7),%s\n", t == CPP_TYPE_DOUBLE ? 'D' : 'S', c1,
offset<<2, c2, RegNamesUpper[ap->Args[i++].ArgReg]);
if(t == CPP_TYPE_DOUBLE)
++offset;
++offset;
}
else if(((k - i) >= 2) && (ap->Args[i].ArgReg < ap->Args[i+1].ArgReg) &&
ap->Args[i+1].ArgReg < REG_FP0 && !(Flags & FLAG_NOMOVEM))
{
DoOutput(/*(*/"\tMOVEM.L\t%s%02ld%sA7),%s", c1, (offset++)<<2, c2,
RegNamesUpper[ap->Args[i++].ArgReg]);
do
{
DoOutput("/%s", RegNamesUpper[ap->Args[i++].ArgReg]);
++offset;
} while((i < k) && (ap->Args[i-1].ArgReg < ap->Args[i].ArgReg) &&
ap->Args[i].ArgReg < REG_FP0);
DoOutput("\n");
}
else
{
DoOutput(/*(*/"\tMOVE%s.L\t%s%02ld%sA7),%s\n",
ap->Args[i].ArgReg >= REG_A0 ? "A" : "", c1, (offset++)<<2, c2,
RegNamesUpper[ap->Args[i].ArgReg]);
++i;
}
}
if(i < ap->NumArgs)
{
if(ap->Args[i].ArgReg > 7)
DoOutput(/*(*/"\tLEA\t%s%02ld%sA7),%s\n", c1, offset<<2, c2,
RegNamesUpper[ap->Args[i].ArgReg]);
else if(offset <= 2)
DoOutput("\tMOVE.L\tA7,%s\n\tADDQ.L\t#%02ld,%s\n",
RegNamesUpper[ap->Args[i].ArgReg],offset<<2,
RegNamesUpper[ap->Args[i].ArgReg]);
else
DoOutput(/*(*/"\tPEA\t%s%ld%sA7)\n\tMOVE.L\t(A7)+,%s\n",c1,
offset<<2, c2,RegNamesUpper[ap->Args[i].ArgReg]);
}
}
else
{
i = ap->NumArgs;
while(i)
{
if(ap->Args[i-1].ArgReg >= REG_FP0)
{
ULONG t;
struct ClibData *cd;
cd = GetClibFunc(name, ap, flags);
if(cd && IsCPPType(&cd->Args[i-1], CPP_TYPE_DOUBLE))
t = CPP_TYPE_DOUBLE;
else if(cd && IsCPPType(&cd->Args[i-1], CPP_TYPE_FLOAT))
t = CPP_TYPE_FLOAT;
else
{
DoError(ERR_LONG_DOUBLE, ap->Line);
t = CPP_TYPE_FLOAT;
}
DoOutput(/*(*/"\tFMOVE.%lc\t%s%02ld%sA7),%s\n", t == CPP_TYPE_DOUBLE ? 'D' : 'S',
c1, offset<<2, c2, RegNamesUpper[ap->Args[--i].ArgReg]);
if(t == CPP_TYPE_DOUBLE)
++offset;
++offset;
}
else if((i >= 2) && (ap->Args[i-1].ArgReg < ap->Args[i-2].ArgReg) &&
ap->Args[i-2].ArgReg < REG_FP0 && !(Flags & FLAG_NOMOVEM))
{
DoOutput(/*(*/"\tMOVEM.L\t%s%02ld%sA7),%s", c1, (offset++)<<2, c2,
RegNamesUpper[ap->Args[--i].ArgReg]);
do
{
DoOutput("/%s", RegNamesUpper[ap->Args[--i].ArgReg]);
++offset;
} while(i && (ap->Args[i].ArgReg < ap->Args[i-1].ArgReg) &&
ap->Args[i-1].ArgReg < REG_FP0);
DoOutput("\n");
}
else
{
--i;
DoOutput(/*(*/"\tMOVE%s.L\t%s%02ld%sA7),%s\n",
ap->Args[i].ArgReg >= REG_A0 ? "A" : "", c1, (offset++)<<2, c2,
RegNamesUpper[ap->Args[i].ArgReg]);
}
}
}
DoOutput(/*(*/"\tJSR\t%s-%03ld%sA6)\n", c1, ap->Bias, c2);
if(fregs)
{
DoOutput("\tFMOVEM.X\t(A7)+,");
for(i = 0; i <= 7; ++i)
{
if(fregs & (1 << i))
{
fregs ^= 1 << i;
DoOutput(RegNamesUpper[REG_FP0 + i]);
if(fregs)
DoOutput("/");
}
}
DoOutput("\n");
}
if(registers)
{
if(Flags & FLAG_NOMOVEM)
{
for(i = 15; i >= 0; --i)
{
if(registers & (1 << i))
DoOutput("\tMOVE%s.L\t(A7)+,%s\n", i >= REG_A0 ? "A" : "", RegNamesUpper[i]);
}
}
else
{
DoOutput("\tMOVEM.L\t(A7)+,");
for(i = 0; i <= 15; ++i)
{
if(registers & (1 << i))
{
registers ^= 1 << i;
DoOutput(RegNamesUpper[i]);
if(registers)
DoOutput("/");
}
}
DoOutput("\n");
}
}
else
DoOutput("\tMOVEA.L\t(A7)+,A6\n");
return DoOutput("\tRTS\n");
}
ULONG FuncAsmCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG registers, a[5], offset = 1, pos = 4, baseref;
LONG i = strlen(ShortBaseNameUpper);
UWORD *data;
UWORD fregs;
data = (UWORD *) tempbuf;
if(CheckError(ap, AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
registers = GetRegisterData(ap);
fregs = GetFRegisterData(ap);
a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
a[3] = (i + 6 + 3)>>2;
DoOutputDirect(a, 16);
DoOutputDirect(ShortBaseNameUpper, i);
DoOutputDirect("_STUBS\0\0\0", (a[3]<<2)-i);
data[0] = 0;
data[1] = HUNK_CODE;
data[2] = 0;
/* data[3] is size */
if(!registers)
{
data[pos++] = 0x2F0E; /* MOVE.L A6,-(A7) */
++offset; /* one long more on stack */
}
else
{
if(Flags & FLAG_NOMOVEM)
{
for(i = 0; i <= 15; ++i)
{
if(registers & (1<< (16+i)))
{
data[pos++] = 0x2F00 + i; /* MOVE.L xxx,-(A7) */
++offset;
}
}
}
else
{
ULONG l;
data[pos++] = 0x48E7; /* MOVEM.L xxx,-(A7) */
data[pos++] = registers; /* store MOVEM.L registers */
for(l = (UWORD) registers; l; l >>= 1)
{
if(l & 1)
++offset; /* get offset addition */
}
}
}
if(fregs)
{
ULONG l;
data[pos++] = 0xF227; /* FMOVEM.X xxx,-(A7) */
data[pos++] = 0xE000 + ((fregs>>8)&0xFF);
for(l = (UBYTE) fregs; l; l >>= 1)
{
if(l & 1)
offset+=3; /* get offset addition */
}
}
baseref = pos+1-4; /* one word later (MOVE) - 2 header longs */
if(Flags & FLAG_SMALLDATA)
{
data[pos++] = 0x2C6C; /* MOVEA.L base(A4),A6 */
data[pos++] = 0; /* place for base reference */
}
else
{
data[pos++] = 0x2C79; /* MOVEA.L base,A6 */
data[pos++] = 0; /* place for base reference */
data[pos++] = 0;
}
pos = AsmStackCopy(data+pos, ap, flags, offset) - data;
/* here comes the base reference */
data[pos++] = 0x4EAE; /* JSR xxx(A6) */
data[pos++] = -ap->Bias; /* JSR offset */
if(fregs)
{
data[pos++] = 0xF21F; /* FMOVEM.X (A7)+,xxx */
data[pos++] = 0xD000 + (fregs&0xFF);
}
if(registers)
{
if(Flags & FLAG_NOMOVEM)
{
for(i = 15; i >= 0; --i)
{
if(registers & (1<<(16+i))) /* MOVE.L (A7)+,xxx */
data[pos++] = 0x201F + ((i&7)<<9) + ((i>>3)<<6);
}
}
else
{
data[pos++] = 0x4CDF; /* MOVEM.L (A7)+,xxx */
data[pos++] = (registers >> 16); /* store MOVEM.L registers */
}
}
else
data[pos++] = 0x2C5F; /* MOVE.L (A7)+,A6 */
data[pos++] = 0x4E75; /* RTS */
if(pos & 1)
data[pos++] = 0; /* round to long */
data[3] = (pos-4)>>1; /* store hunk len */
DoOutputDirect(data, pos<<1);
a[0] = HUNK_EXT;
a[1] = ((Flags & FLAG_SMALLDATA ? EXT_REF16 : EXT_REF32) << 24) +
((strlen(BaseName) + 1 + 3)>>2);
a[2] = ('_' << 24);
DoOutputDirect(a, 9);
DoOutputDirect(BaseName, (((UWORD) a[1])<<2)-1);
a[0] = 1; a[1] = baseref << 1;
DoOutputDirect(a, 8);
/* here come the XDEF name references */
OutputXDEF("_%s", name); /* C name */
if(!(Flags & FLAG_PASCAL))
{
struct ClibData *cd;
OutputXDEF("%s", name); /* ASM name */
if(clibdata)
{
if(!ap->NumArgs)
OutputXDEF("%s_", name); /* C++ name no parameters */
else if((cd = GetClibFunc(name, ap, flags)))
{
ULONG ret = 0;
do /* C++ name with parameters */
{
if((ret = CopyCPPType((STRPTR) data, ret, cd, ap->Args)))
OutputXDEF("%s__%s", name, (STRPTR) data);
} while(ret == 0xFFFFFFFF);
}
}
}
a[0] = 0;
DoOutputDirect(a, 4);
if(!(Flags & FLAG_NOSYMBOL))
{
a[0] = HUNK_SYMBOL;
DoOutputDirect(a, 4);
OutputSYMBOL("_%s", name); /* C name */
if(!(Flags & FLAG_PASCAL))
{
struct ClibData *cd;
OutputSYMBOL("%s", name); /* ASM name */
if(clibdata)
{
if(!ap->NumArgs)
OutputSYMBOL("%s_", name); /* C++ name no parameters */
else if((cd = GetClibFunc(name, ap, flags)))
{
ULONG ret = 0;
do /* C++ name with parameters */
{
if((ret = CopyCPPType((STRPTR) data, ret, cd, ap->Args)))
OutputSYMBOL("%s__%s", name, (STRPTR) data);
} while(ret == 0xFFFFFFFF);
}
}
}
a[0] = 0;
DoOutputDirect(a, 4);
}
a[0] = HUNK_END;
return DoOutputDirect(a, 4);
}
/* Directly called by FuncInline also! */
ULONG FuncCSTUBS(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
struct ClibData *f, *t;
STRPTR ret = "return ";
ULONG i;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
if(!(f = GetClibFunc(ap->FuncName, ap, 0)))
return 1;
t = GetClibFunc(name, ap, flags);
if(IsCPPType(&f->ReturnType, CPP_TYPE_VOID))
ret = 0;
if(!OutClibType(&f->ReturnType, name) || !DoOutput("("/*)*/))
return 0;
for(i = 0; i < ap->NumArgs-1; i++)
{
if(!OutClibType(&f->Args[i], ap->Args[i].ArgName) || !DoOutput(", "))
return 0;
}
if(t && t->Args[i].Type != CPP_TYPE_VARARGS)
{
if(!OutClibType(&t->Args[i], ap->Args[i].ArgName) || !DoOutput(", "))
return 0;
}
else if(ap->NumArgs == 1 && !DoOutput("ULONG tag, "))
return 0;
if(!DoOutput(/*(*/"...)\n{\n %s%s("/*)*/, ret, ap->FuncName))
return 0;
for(i = 0; i < ap->NumArgs-1; i++)
{
if(!DoOutput("%s, ", ap->Args[i].ArgName))
return 0;
}
if(!DoOutput("("/*)*/) || !OutClibType(&f->Args[ap->NumArgs-1],0))
return 0;
if(t && t->Args[i].Type != CPP_TYPE_VARARGS)
{
if(!DoOutput(/*((*/") &%s);\n}\n\n", ap->Args[ap->NumArgs-1].ArgName))
return 0;
}
else if(ap->NumArgs == 1)
{
if(!DoOutput(/*((*/") &tag);\n}\n\n"))
return 0;
}
else if (!DoOutput(/*(*/") ((ULONG) &%s + sizeof("/*))*/,
ap->Args[ap->NumArgs-2].ArgName) || !OutClibType(&f->Args[ap->NumArgs-2],0)
|| !DoOutput(/*(((*/")));\n}\n\n"))
return 0;
return 1;
}
ULONG FuncLVOXDEF(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
Flags |= FLAG_DONE; /* We did something */
return DoOutput("\t\tXDEF\t_LVO%s\n", name);
}
ULONG FuncLVO(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
Flags |= FLAG_DONE; /* We did something */
return DoOutput("\n_LVO%-24s\tEQU\t-%ld", name, ap->Bias);
}
ULONG FuncLVOLib(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG a[1], j;
Flags |= FLAG_DONE; /* We did something */
a[0] = (EXT_ABS << 24) + (((j=strlen(name)) + 4 + 3)>>2);
DoOutputDirect(a, 4);
DoOutputDirect("_LVO", 4);
DoOutputDirect(name, j);
DoOutputDirect("\0\0\0", ((j+3)&(~3))-j);
a[0] = -ap->Bias;
return DoOutputDirect(a, 4);
}
ULONG FuncLocCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG a[5];
STRPTR str2 = Flags & FLAG_LOCALREG ? "rE" : "";
LONG i = strlen(ShortBaseNameUpper);
ULONG j;
struct ClibData *cd = 0;
if(CheckError(ap, AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
a[3] = (i + 4 + 3)>>2;
DoOutputDirect(a, 16);
DoOutputDirect(ShortBaseNameUpper, i);
DoOutputDirect("_LOC\0\0\0", (a[3]<<2)-i);
if(Flags & FLAG_LOCALREG)
{
if((flags & FUNCFLAG_TAG))
{
j = ap->Args[ap->NumArgs-1].ArgReg;
a[0] = HUNK_CODE; a[1] = 4;
a[2] = 0x2F000000 + (j << 16); /* MOVE <ea>,-(A7) */
DoOutputDirect(a, 10);
a[1] = 0x4EAE0000 + (UWORD) (- ap->Bias); /* JSR instruction */
a[2] = 0x201F4E75; /* MOVE (A7)+,<ea> */
a[3] = 0;
if(j > 7)
{ /* LEA x(A7),Ax */
j -= 8;
a[0] = 0x41EF0008 | (j << 25);
a[2] += 0x400000; /* set A flag */
}
else
{ /* MOVE.L A7,Dx -- ADDQ.L #8,Dx */
a[0] = 0x200F5080 | j | (j << 25);
}
a[2] += j << 25;
DoOutputDirect(a, 14);
}
else
{
a[0] = HUNK_CODE; a[1] = 1;
a[2] = 0x4EEE0000 + (UWORD) (- ap->Bias); /* JMP instruction */
DoOutputDirect(a, 12);
}
}
else
{
ULONG registers, offset = 1, pos = 4;
UWORD *data;
data = (UWORD *) tempbuf;
registers = GetRegisterData(ap);
data[0] = 0;
data[1] = HUNK_CODE;
data[2] = 0;
/* data[3] is size */
if(!registers) /* happens only when !(ap->Flags & AMIPRAG_A6USE) */
{
data[pos++] = 0x2F0E; /* MOVE.L A6,-(A7) */
++offset; /* one long more on stack */
}
else
{
if(Flags & FLAG_NOMOVEM)
{
for(i = 0; i <= 15; ++i)
{
if(registers & (1<< (16+i)))
{
data[pos++] = 0x2F00 + i; /* MOVE.L xxx,-(A7) */
++offset;
}
}
}
else
{
ULONG l;
data[pos++] = 0x48E7; /* MOVEM.L xxx,-(A7) */
data[pos++] = registers; /* store MOVEM.L registers */
for(l = (UWORD) registers; l; l >>= 1)
{
if(l & 1)
++offset; /* get offset addition */
}
}
}
if(!(ap->Flags & AMIPRAGFLAG_A6USE)) /* store library base in A6 */
{
data[pos++] = 0x2C6F; /* MOVE.L ofs(A7),A6 */
data[pos++] = (offset++) << 2;
}
pos = AsmStackCopy(data+pos, ap, flags, offset) - data;
/* here comes the base reference */
data[pos++] = 0x4EAE; /* JSR xxx(A6) */
data[pos++] = -ap->Bias; /* JSR offset */
if(registers)
{
if(Flags & FLAG_NOMOVEM)
{
for(i = 15; i >= 0; --i)
{
if(registers & (1<<(16+i))) /* MOVE.L (A7)+,xxx */
data[pos++] = 0x201F + ((i&7)<<9) + ((i>>3)<<6);
}
}
else
{
data[pos++] = 0x4CDF; /* MOVEM.L (A7)+,xxx */
data[pos++] = (registers >> 16); /* store MOVEM.L registers */
}
}
else
data[pos++] = 0x2C5F; /* MOVE.L (A7)+,A6 */
data[pos++] = 0x4E75; /* RTS */
if(pos & 1)
data[pos++] = 0; /* round to long */
data[3] = (pos-4)>>1; /* store hunk len */
DoOutputDirect(data, pos<<1);
}
a[0] = HUNK_EXT;
DoOutputDirect(a,4);
/* here come the XDEF name references */
OutputXDEF("%s", name); /* ASM names */
OutputXDEF("LOC_%s", name);
OutputXDEF("_%s", name); /* C names */
OutputXDEF("_LOC_%s", name);
if(!ap->NumArgs && clibdata)
{
OutputXDEF("%s__%sP07Library", name, str2); /* C++ names no parameters */
OutputXDEF("LOC_%s__%sP07Library", name, str2);
}
else if((cd = GetClibFunc(name, ap, flags)))
{
STRPTR txt;
ULONG ret = 0;
txt = (STRPTR) tempbuf;
do
{
if((ret = CopyCPPType(txt, ret, cd, ap->Args)))
{ /* C++ names with parameters */
if(!(ap->Flags & AMIPRAGFLAG_A6USE))
{
OutputXDEF("%s__%sP07Library%s", name, str2, txt);
OutputXDEF("LOC_%s__%sP07Library%s", name, str2, txt);
}
else
{
OutputXDEF("%s__%s", name, txt);
OutputXDEF("LOC_%s__%s", name, txt);
}
}
} while(ret == 0xFFFFFFFF);
}
a[0] = 0;
DoOutputDirect(a, 4);
if(!(Flags & FLAG_NOSYMBOL))
{
a[0] = HUNK_SYMBOL;
DoOutputDirect(a, 4);
OutputSYMBOL("%s", name); /* ASM names */
OutputSYMBOL("LOC_%s", name);
OutputSYMBOL("_%s", name); /* C names */
OutputSYMBOL("_LOC_%s", name);
if(!ap->NumArgs && clibdata)
{
OutputSYMBOL("%s__%sP07Library", name, str2); /* C++ names no parameters */
OutputSYMBOL("LOC_%s__%sP07Library", name, str2);
}
else if(cd)
{
STRPTR txt;
ULONG ret = 0;
txt = (STRPTR) tempbuf;
do
{
if((ret = CopyCPPType(txt, ret, cd, ap->Args)))
{ /* C++ names with parameters */
if(!(ap->Flags & AMIPRAGFLAG_A6USE))
{
OutputSYMBOL("%s__%sP07Library%s", name, str2, txt);
OutputSYMBOL("LOC_%s__%sP07Library%s", name, str2, txt);
}
else
{
OutputSYMBOL("%s__%s", name, txt);
OutputSYMBOL("LOC_%s__%s", name, txt);
}
}
} while(ret == 0xFFFFFFFF);
}
a[0] = 0;
DoOutputDirect(a, 4);
}
a[0] = HUNK_END;
return DoOutputDirect(a, 4);
}
ULONG FuncLocText(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
struct ClibData *cd;
LONG i;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
if(!(cd = GetClibFunc(name, ap, flags)))
return 1;
OutClibType(&cd->ReturnType, 0);
DoOutput(" LOC_%s("/*)*/, name);
if(!(ap->Flags & AMIPRAGFLAG_A6USE))
{
if(Flags & FLAG_LOCALREG)
DoOutput("register __a6 ");
DoOutput("struct Library * libbase");
if(ap->NumArgs)
DoOutput(", ");
}
if(ap->NumArgs)
{
for(i = 0; i < ap->NumArgs-1; i++)
{
if(((Flags & FLAG_LOCALREG &&
!DoOutput("register __%s ", RegNames[ap->Args[i].ArgReg]))) ||
!OutClibType(&cd->Args[i], ap->Args[i].ArgName) || !DoOutput(", "))
return 0;
}
if(flags & FUNCFLAG_NORMAL)
{
if(((Flags & FLAG_LOCALREG &&
!DoOutput("register __%s ", RegNames[ap->Args[i].ArgReg]))) ||
!OutClibType(&cd->Args[i], ap->Args[i].ArgName) ||
!DoOutput(/*(*/");\n"))
return 0;
if(BaseName)
{
DoOutput("#define %s("/*)*/, name);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("%lc, ", (i+'a'));
DoOutput(/*(*/"%lc) LOC_%s((struct Library *) %s, "/*)*/,(i+'a'),
name, BaseName);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("%lc, ",(i+'a'));
return DoOutput(/*(*/"%lc)\n\n",(i+'a'));
}
}
else
return DoOutput(/*(*/"...);\n");
}
else if(BaseName)
return DoOutput(/*(*/");\n#define %s(a) LOC_%s((struct Library *) a)\n\n",
name, name);
else
return DoOutput(/*(*/");\n");
return 1;
}
ULONG FuncInline(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG noret = 0, a45 = 0, i, j;
LONG fp = -1;
struct ClibData *cd;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
if(flags & FUNCFLAG_ALIAS)
{
if(flags & FUNCFLAG_TAG)
return DoOutput("#ifndef NO_%sINLINE_STDARG\n#define %s %s\n#endif\n\n",
Flags & FLAG_POWERUP ? "PPC" : "", name, ap->TagName);
DoOutput("#define %s("/*)*/, name);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("%s, ", ap->Args[i].ArgName);
DoOutput(/*(*/"%s) %s("/*)*/, ap->Args[i].ArgName, ap->FuncName);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("(%s), ", ap->Args[i].ArgName);
return DoOutput(/*(*/"(%s))\n\n", ap->Args[i].ArgName);
}
if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
return 1;
if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
noret = 1; /* this is a void function */
if(ap->Flags & AMIPRAGFLAG_A5USE)
a45 = REG_A5;
if(ap->Flags & AMIPRAGFLAG_A4USE)
{
if(a45)
{
DoError(ERR_INLINE_A4_AND_A5, ap->Line);
return 1; /* skip this entry */
}
a45 = REG_A4;
}
if(a45 && (ap->Flags & AMIPRAGFLAG_D7USE))
{
DoError(ERR_INLINE_D7_AND_A45, ap->Line);
return 1; /* skip this entry */
}
if((flags & FUNCFLAG_TAG))
{
if(!(Flags & FLAG_INLINESTUB)) /* no stubs */
{
DoOutput("#ifndef NO_%sINLINE_STDARG\n#define %s("/*)*/,
Flags & FLAG_POWERUP ? "PPC" : "", name);
for(i = 0; i < ap->NumArgs-1; ++i)
{
DoOutput("%s, ", ap->Args[i].ArgName);
}
DoOutput(/*(*/"tags...) \\\n\t({ULONG _tags[] = {tags}; %s("/*}))*/,
ap->FuncName);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("(%s), ", ap->Args[i].ArgName);
DoOutput("("/*)*/);
OutClibType(&cd->Args[i], 0);
return DoOutput(/*({((*/") _tags);})\n#endif\n\n");
}
else
return FuncCSTUBS(ap, flags, name);
/* call CSTUBS, as this equals the method used there */
}
if(Flags & FLAG_INLINENEW) /* new style */
{
STRPTR funcpar = "";
DoOutput("#define %s("/*)*/, name);
for(i = 0; i < cd->NumArgs; ++i)
{
if(cd->Args[i].Flags & CPP_FLAG_FUNCTION)
funcpar = "FP";
}
if(ap->NumArgs)
{
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("%s, ", ap->Args[i].ArgName);
DoOutput("%s", ap->Args[i].ArgName);
}
DoOutput(/*(*/") \\\n\tLP%ld%s%s%s%s(0x%lx, "/*)*/, ap->NumArgs,
(noret ? "NR" : ""), (a45 ? RegNamesUpper[a45] : (STRPTR) ""),
(BaseName ? "" : "UB"), funcpar, ap->Bias);
if(!noret)
{
OutClibType(&cd->ReturnType, 0);
DoOutput(", ");
}
DoOutput("%s, ", name);
for(i = 0; i < ap->NumArgs; ++i)
{
j = ap->Args[i].ArgReg;
if(a45 && (j == REG_A4 || j == REG_A5))
j = REG_D7;
if(cd->Args[i].Flags & CPP_FLAG_FUNCTION)
{
DoOutput("__fpt"); fp = i;
}
else
OutClibType(&cd->Args[i], 0);
DoOutput(", %s, %s%s", ap->Args[i].ArgName, RegNames[j],
(i == ap->NumArgs-1 && !BaseName ? "" : ", "));
}
if(BaseName) /* was "##base" used? */
DoOutput("\\\n\t, %s_BASE_NAME", ShortBaseNameUpper);
if(fp >= 0)
{
DoOutput(", ");
OutClibType(&cd->Args[fp], "__fpt");
}
if(Flags & FLAG_POWERUP)
DoOutput(", IF_CACHEFLUSHALL, NULL, 0, IF_CACHEFLUSHALL, NULL, 0");
return DoOutput(/*(*/")\n\n");
}
/* old mode or stubs mode */
DoOutput("%s%s__inline ", Flags & FLAG_INLINESTUB ? "" : "extern ",
Flags & FLAG_POWERUP ? "static " : "");
OutClibType(&cd->ReturnType, 0);
DoOutput("\n%s(%s"/*)*/, name, (BaseName ?
(ap->NumArgs ? "BASE_PAR_DECL " : "BASE_PAR_DECL0") : ""));
for(i = 0; i < ap->NumArgs; ++i)
{
OutClibType(&cd->Args[i], ap->Args[i].ArgName);
if(i < ap->NumArgs-1)
DoOutput(", ");
}
if(Flags & FLAG_POWERUP)
{
DoOutput(/*(*/")\n{\n\tstruct Caos MyCaos;\n"/*}*/
"\tMyCaos.M68kCacheMode\t= IF_CACHEFLUSHALL;\n"
"/*\tMyCaos.M68kStart\t= NULL;\t*/\n"
"/*\tMyCaos.M68kSize\t\t= 0;\t*/\n"
"\tMyCaos.PPCCacheMode\t= IF_CACHEFLUSHALL;\n"
"/*\tMyCaos.PPCStart\t\t= NULL;\t*/\n"
"/*\tMyCaos.PPCSize\t\t= 0;\t*/\n");
if(ap->NumArgs)
{
for(i = 0; i < ap->NumArgs; ++i)
{
DoOutput("\tMyCaos.%s\t\t= (ULONG) %s;\n",
RegNames[ap->Args[i].ArgReg], ap->Args[i].ArgName);
}
}
DoOutput("\tMyCaos.caos_Un.Offset\t= %ld;\n", -ap->Bias);
if(BaseName)
DoOutput("\tMyCaos.a6\t\t= (ULONG) %s_BASE_NAME;\n", ShortBaseNameUpper);
if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
DoOutput(/*{*/"\tPPCCallOS(&MyCaos);\n}\n\n");
else
{
DoOutput("\treturn(("/*))*/);
OutClibType(&cd->ReturnType, 0);
DoOutput(/*{((*/")PPCCallOS(&MyCaos));\n}\n\n");
}
return Output_Error;
}
DoOutput(/*(*/")\n{\n%s"/*}*/, (BaseName ? " BASE_EXT_DECL\n" : ""));
if(!noret)
{
DoOutput(" register ");
OutClibType(&cd->ReturnType, "res");
DoOutput(" __asm(\"d0\");\n");
}
if(BaseName)
DoOutput(" register struct %s *a6 __asm(\"a6\") = BASE_NAME;\n",
GetBaseType());
for(i = 0; i < ap->NumArgs; ++i)
{
j = ap->Args[i].ArgReg;
if(a45 && (j == REG_A4 || j == REG_A5))
j = REG_D7;
DoOutput(" register ");
OutClibType(&cd->Args[i], RegNames[j]);
DoOutput(" __asm(\"%s\") = %s;\n", RegNames[j], ap->Args[i].ArgName);
}
if(a45)
{
DoOutput(" __asm volatile (\"exg d7,%s\\n\\t"/*)*/
"jsr a6@(-0x%lx:W)\\n\\texg d7,%s\"\n", RegNames[a45],
ap->Bias, RegNames[a45]);
}
else
DoOutput(" __asm volatile (\"jsr a6@(-0x%lx:W)\"\n"/*)*/, ap->Bias);
DoOutput(noret ? " : /* No Output */\n" : " : \"=r\" (res)\n");
DoOutput(" : ");
if(BaseName)
DoOutput("\"r\" (a6)%s", (ap->NumArgs ? ", ": ""));
for(i = 0; i < ap->NumArgs; ++i)
{
j = ap->Args[i].ArgReg;
if(a45 && (j == REG_A4 || j == REG_A5))
j = REG_D7;
DoOutput("\"r\" (%s)%s", RegNames[j], (i < ap->NumArgs-1 ? ", " : ""));
}
DoOutput("\n : \"d0\", \"d1\", \"a0\", \"a1\", \"fp0\", \"fp1\"");
if(noret)
return DoOutput(/*({*/", \"cc\", \"memory\");\n}\n\n");
else
return DoOutput(/*({*/", \"cc\", \"memory\");\n return res;\n}\n\n");
}
ULONG FuncPowerUP(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG i;
struct ClibData *cd;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
if(flags & FUNCFLAG_ALIAS)
{
if(flags & FUNCFLAG_TAG)
return DoOutput("#ifndef NO_PPCINLINE_STDARG\n#define %s %s\n#endif\n\n", name, ap->TagName);
DoOutput("#define %s("/*)*/, name);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("%s, ", ap->Args[i].ArgName);
DoOutput(/*(*/"%s) %s("/*)*/, ap->Args[i].ArgName, ap->FuncName);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("(%s), ", ap->Args[i].ArgName);
return DoOutput(/*(*/"(%s))\n\n", ap->Args[i].ArgName);
}
if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
return 1;
if(flags & FUNCFLAG_TAG)
{
DoOutput("#ifndef NO_PPCINLINE_STDARG\n#define %s("/*)*/, name);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("%s, ", ap->Args[i].ArgName);
DoOutput(/*(*/"tags...) \\\n\t({ULONG _tags[] = {tags}; %s("/*)})*/,
ap->FuncName);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("(%s), ", ap->Args[i].ArgName);
DoOutput("("/*)*/);
OutClibType(&cd->Args[i], 0);
return DoOutput(/*({((*/") _tags);})\n#endif\n\n");
}
DoOutput("#define\t%s("/*)*/, name);
if(ap->NumArgs)
{
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("%s, ", ap->Args[i].ArgName);
DoOutput(/*(*/"%s)\t_%s("/*)*/, ap->Args[i].ArgName, name);
if(BaseName)
DoOutput("%s_BASE_NAME, ", ShortBaseNameUpper);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("%s, ", ap->Args[i].ArgName);
DoOutput(/*(*/"%s)\n\n", ap->Args[i].ArgName);
}
else if(BaseName)
DoOutput(/*(*/")\t_%s(%s_BASE_NAME)\n\n", name, ShortBaseNameUpper);
else
DoOutput(/*(*/")\t_%s()\n\n", name);
DoOutput("static __inline ");
OutClibType(&cd->ReturnType, 0);
DoOutput("\n_%s("/*)*/, name);
if(BaseName)
DoOutput("void * %s%s", BaseName, ap->NumArgs ? ", " : "");
for(i = 0; i < ap->NumArgs; ++i)
{
OutClibType(&cd->Args[i], ap->Args[i].ArgName);
if(i < ap->NumArgs-1)
DoOutput(", ");
}
DoOutput(/*(*/")\n{\n\tstruct Caos MyCaos;\n"/*}*/
"\tMyCaos.M68kCacheMode\t= IF_CACHEFLUSHALL;\n"
"/*\tMyCaos.M68kStart\t= NULL;\t*/\n"
"/*\tMyCaos.M68kSize\t\t= 0;\t*/\n"
"\tMyCaos.PPCCacheMode\t= IF_CACHEFLUSHALL;\n"
"/*\tMyCaos.PPCStart\t\t= NULL;\t*/\n"
"/*\tMyCaos.PPCSize\t\t= 0;\t*/\n");
if(ap->NumArgs)
{
for(i = 0; i < ap->NumArgs; ++i)
{
DoOutput("\tMyCaos.%s\t\t= (ULONG) %s;\n",
RegNames[ap->Args[i].ArgReg], ap->Args[i].ArgName);
}
}
DoOutput("\tMyCaos.caos_Un.Offset\t= %ld;\n", -ap->Bias);
if(BaseName)
DoOutput("\tMyCaos.a6\t\t= (ULONG) %s;\n", BaseName);
if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
DoOutput(/*{*/"\tPPCCallOS(&MyCaos);\n}\n\n");
else
{
DoOutput("\treturn(("/*))*/);
OutClibType(&cd->ReturnType, 0);
DoOutput(/*{((*/")PPCCallOS(&MyCaos));\n}\n\n");
}
return Output_Error;
}
ULONG FuncFPCUnit(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
LONG i;
struct ClibData *cd;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_PPC))
return 1;
else if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
return 1;
if(!FuncFPCType(ap, flags, name))
return 0;
DoOutput("BEGIN\n ASM\n\tMOVE.L\tA6,-(A7)\n");
for(i = 0; i < ap->NumArgs; ++i)
DoOutput("\tMOVE%s.L\t%s,%s\n", ap->Args[i].ArgReg >= REG_A0 ? "A" : "",
ap->Args[i].ArgName, RegNamesUpper[ap->Args[i].ArgReg]);
if(BaseName)
DoOutput("\tMOVEA.L\t%s,A6\n", BaseName);
DoOutput("\tJSR\t-%03ld(A6)\n\tMOVEA.L\t(A7)+,A6\n", ap->Bias);
if(!IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
{
if(!cd->ReturnType.PointerDepth &&
cd->ReturnType.Flags == CPP_FLAG_BOOLEAN)
DoOutput("\tTST.W\tD0\n\tBEQ.B\t@end\n\tMOVEQ\t#1,D0\n"
" @end:\tMOVE.B\tD0,@RESULT\n");
else
DoOutput("\tMOVE.L\tD0,@RESULT\n");
}
return DoOutput(" END;\nEND;\n\n");
}
ULONG FuncFPCType(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG ret = 1;
LONG i;
struct ClibData *cd;
if(CheckError(ap, AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_PPC))
return 1;
else if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
return 1;
if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
{
ret = 0; DoOutput("PROCEDURE %s", name);
}
else
DoOutput("FUNCTION %s", name);
if(ap->NumArgs)
{
DoOutput("("/*)*/);
for(i = 0; i < ap->NumArgs;)
{
OutPASCALType(&cd->Args[i], ap->Args[i].ArgName, 0);
if(++i != ap->NumArgs)
DoOutput("; ");
}
DoOutput(/*(*/")");
}
if(ret)
OutPASCALType(&cd->ReturnType, "", 1);
Flags |= FLAG_DONE; /* We did something */
return DoOutput(";\n");
}
ULONG FuncBMAP(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
UBYTE reg, i;
if(CheckError(ap, AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_A6USE|AMIPRAGFLAG_A5USE|AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE; /* We did something */
for(i = 0; BMAPSpecial[i]; ++i)
{
if(!stricmp(name, BMAPSpecial[i]))
{
DoOutput("x"); break;
}
}
DoOutput(name);
reg = 0; DoOutputDirect(®, 1);
reg = (-ap->Bias)>>8; DoOutputDirect(®, 1);
reg = -ap->Bias; DoOutputDirect(®, 1);
for(i = 0; i < ap->NumArgs; ++i)
{
reg = 1+ap->Args[i].ArgReg; DoOutputDirect(®, 1);
}
reg = 0;
return DoOutputDirect(®, 1);
}
ULONG FuncVBCCInline(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
struct ClibData *cd;
STRPTR c1, c2;
ULONG i;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
return 1;
if(!(cd = GetClibFunc(name, ap, flags)))
return 1;
c1 = Flags & FLAG_NEWSYNTAX ? "(" : ""; /*)*/
c2 = Flags & FLAG_NEWSYNTAX ? "," : "("; /*)*/
Flags |= FLAG_DONE; /* We did something */
if(flags & FUNCFLAG_ALIAS)
{
DoOutput("#define %s("/*)*/, name);
for(i = 0; i < ap->NumArgs-1; ++i)
DoOutput("%s, ", ap->Args[i].ArgName);
DoOutput(/*(*/"%s) __%s("/*)*/, ap->Args[i].ArgName, ap->FuncName);
for(i = 0; i < ap->NumArgs; ++i)
DoOutput("(%s), ", ap->Args[i].ArgName);
return DoOutput(/*(*/"%s)\n\n", BaseName);
}
OutClibType(&cd->ReturnType, 0);
DoOutput(" __%s("/*)*/, name);
for(i = 0; i < ap->NumArgs; ++i)
{
DoOutput("__reg(\"%s\") ", RegNames[ap->Args[i].ArgReg]);
OutClibType(&cd->Args[i], ap->Args[i].ArgName);
if(i < ap->NumArgs-1)
DoOutput(", ");
}
if(BaseName)
{
if(ap->NumArgs)
DoOutput(", ");
DoOutput("__reg(\"a6\") void *");
}
DoOutput(/*((*/")=\"\\tJSR\\t%s-%ld%sA6)\";\n", c1, ap->Bias, c2);
DoOutput("#define %s("/*)*/, name);
for(i = 0; i < ap->NumArgs; ++i)
{
DoOutput("%s", ap->Args[i].ArgName);
if(i < ap->NumArgs-1)
DoOutput(", ");
}
DoOutput(/*(*/") __%s("/*)*/, name);
for(i = 0; i < ap->NumArgs; ++i)
{
DoOutput("(%s)", ap->Args[i].ArgName);
if(i < ap->NumArgs-1)
DoOutput(", ");
}
if(BaseName)
{
if(ap->NumArgs)
DoOutput(", ");
DoOutput("%s", BaseName);
}
return DoOutput(/*(*/")\n\n");
}
ULONG FuncVBCCWOSText(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG i, k, count, ofs;
struct ClibData *cd = 0;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG))
return 1;
if((flags & FUNCFLAG_TAG) && !(ap->Flags & AMIPRAGFLAG_PPC) &&!(cd = GetClibFunc(name, ap, flags)))
return 1;
if((ap->Flags & AMIPRAGFLAG_PPC) && !BaseName &&
((ap->Flags & (AMIPRAGFLAG_PPC0|AMIPRAGFLAG_PPC2)) || !(Flags & FLAG_WOSLIBBASE)))
{
DoError(ERR_MISSING_BASENAME, ap->Line);
return 1;
}
Flags |= FLAG_DONE;
if(Flags & FLAG_ASMSECTION)
DoOutput("\t.section %s,\"cr\"\n", name);
DoOutput("\t.text\n\t.align\t3\n");
if(Flags & FLAG_WOSLIBBASE) /* PPCBase already in r3, LibBase in r4 */
{
if(ap->Flags & (AMIPRAGFLAG_PPC0|AMIPRAGFLAG_PPC2))
DoOutput("\t.extern _%s\n", BaseName);
DoOutput("\t.global __%s\n__%s:\n", name, name);
}
else
{
if(BaseName)
DoOutput("\t.extern _%s\n", BaseName);
if(!(ap->Flags & AMIPRAGFLAG_PPC))
DoOutput("\t.extern _PowerPCBase\n");
DoOutput("\t.global _%s\n_%s:\n", name, name);
}
if(ap->Flags & AMIPRAGFLAG_PPC2)
{
DoOutput("\tstw\tr2,20(r1)\n\tmflr\tr0\n\tstw\tr0,16(r1)\n"
"\tlwz\tr2,_%s(r2)\n\tlwz\tr0,-%ld(r2)\n\tmtlr\tr0\n\tblrl\n"
"\tlwz\tr0,16(r1)\n\tlwz\tr2,20(r1)\n\tmtlr\tr0\n\tblr\n",
BaseName,ap->Bias-2);
}
else if(ap->Flags & AMIPRAGFLAG_PPC0)
{
DoOutput("\tlwz\tr11,_%s(r2)\n\tlwz\tr0,-%ld(r11)\n\tmtlr\tr0\n\tblrl\n",
BaseName,ap->Bias-2);
}
else if(ap->Flags & AMIPRAGFLAG_PPC)
{
count = ap->NumArgs;
if(Flags & FLAG_WOSLIBBASE) /* LibBase already in r3 */
{
/* init stack frame */
i = (count <= 8) ? 32 : ((56+(count-8)*8+15)&~15); /* stksize */
DoOutput("\tmflr\tr0\n\tstw\tr0,8(r1)\n\tstwu\tr1,-%ld(r1)\n",i);
if(count > 8)
{
/* extra arguments must be passed on the stack */
k = 32-(count-8); /* firstreg */
DoOutput("\tstmw\tr%ld,%ld(r1)\n\tlmw\tr%ld,%ld(r1)\n",
k, 56+(count-8)*4,k,i+56);
if(flags & FUNCFLAG_TAG)
DoOutput("\taddi\tr31,r1,%ld\n", i+20+count*4);
DoOutput("\tstmw\tr%ld,56(r1)\n",k);
}
else if(flags & FUNCFLAG_TAG)
{
DoOutput("\taddi\tr%ld,r1,%ld\n", count+3, i+20+count*4);
--count;
}
}
else /* Args must be shifted! */
{
/* init stack frame */
i = (count < 8) ? 32 : ((56+(count-7)*8+15)&~15); /* stksize */
DoOutput("\tmflr\tr0\n\tstw\tr0,8(r1)\n\tstwu\tr1,-%ld(r1)\n", i);
if(count > 7)
{
/* extra arguments must be passed on the stack */
if(count == 8)
{
/* special case: move 8th argument into stack frame */
if(flags & FUNCFLAG_TAG)
DoOutput("\taddi\tr10,r1,%ld\n",i+20+count*4);
DoOutput("\tstw\tr10,56(r1)\n");
}
else
{
k = 32-(count-7); /* firstreg */
DoOutput("\tstmw\tr%ld,%ld(r1)\n\tmr\tr%ld,r10\n"
"\tlmw\tr%ld,%ld(r1)\n", k, 56+(count-7)*4, k, k+1, i+56);
if(flags & FUNCFLAG_TAG)
DoOutput("\taddi\tr31,r1,%ld\n", i+20+count*4);
DoOutput("\tstmw\tr%ld,56(r1)\n",k);
}
}
else if(flags & FUNCFLAG_TAG)
{
DoOutput("\taddi\tr%ld,r1,%ld\n", count+3, i+20+count*4);
--count;
}
/* shift all arguments into their following register */
for(k=(count<8)?count:7; k > 0; --k)
DoOutput("\tmr\tr%ld,r%ld\n", 3+k, 2+k);
/* load library base and LVO, then call LVO via LR */
DoOutput("\tlwz\tr3,_%s(r2)\n",BaseName);
}
/* call LVO */
DoOutput("\tlwz\tr0,-%ld(r3)\n\tmtlr\tr0\n\tblrl\n", ap->Bias-2);
/* cleanup stack frame and return */
if(count > 8)
{
k = Flags & FLAG_WOSLIBBASE ? 8 : 7; /* restore saved regs */
DoOutput("\tlmw\tr%ld,%ld(r1)\n", 32-(count-k),56+(count-k)*4);
}
DoOutput("\taddi\tr1,r1,%ld\n\tlwz\tr0,8(r1)\n\tmtlr\tr0\n\tblr\n");
}
else
{
DoOutput("\tmflr\tr0\n\tstw\tr0,8(r1)\n\tstwu\tr1,-0xB0(r1)\n");
/* clear PP_Flags, PP_Stack and PP_StackSize */
DoOutput("\tli\tr11,0\n\tstw\tr11,0x28(r1)\n\tstw\tr11,0x2C(r1)\n"
"\tstw\tr11,0x30(r1)\n");
if(Flags & FLAG_WOSLIBBASE)
DoOutput("\tli\tr11,-%ld\n\tstw\tr4,0x20(r1)\n\tstw\tr11,0x24(r1)\n"
"\tstw\tr4,0x6C(r1)\n",ap->Bias);
else if(!BaseName)
DoOutput("\tli\tr11,-%ld\n\tstw\tr11,0x24(r1)\n",ap->Bias);
else
DoOutput("\tlwz\tr0,_%s(r2)\n\tli\tr11,-%ld\n"
"\tstw\tr0,0x20(r1)\n\tstw\tr11,0x24(r1)\n\tstw\tr0,0x6c(r1)\n",
BaseName,ap->Bias);
ofs = Flags & FLAG_WOSLIBBASE ? 2 : 0;
k = ap->NumArgs - (flags & FUNCFLAG_TAG ? 1 : 0);
for(i = 0; i < k; ++i)
{
if(i + ofs <= 7)
{
if(ap->Args[i].ArgReg == REG_A6)
DoOutput("\tstw\tr%ld,0x20(r1)\n",i+3+ofs);
DoOutput("\tstw\tr%ld,",i+3+ofs);
}
else
{
DoOutput("\tlwz\tr11,%ld(r1)\n",(i+1+ofs)*4+196);
if(ap->Args[i].ArgReg == REG_A6)
DoOutput("\tstw\tr11,0x20(r1)\n");
DoOutput("\tstw\tr11,");
}
DoOutput("%ld(r1)\n", 0x34+4*ap->Args[i].ArgReg);
}
if(flags & FUNCFLAG_TAG)
{
if((i+ofs) <= 7 && cd->Args[i].Type != CPP_TYPE_VARARGS)
DoOutput("\tstw\tr%ld,%ld(r1)\n",i+3+ofs, 0xC4+(ap->NumArgs+ofs)*4);
DoOutput("\taddi\tr11,r1,%ld\n\tstw\tr11,", 0xC4+(ap->NumArgs+ofs)*4);
DoOutput("%ld(r1)\n", 0x34+4*ap->Args[i].ArgReg);
}
if(!(Flags & FLAG_WOSLIBBASE))
DoOutput("\tlwz\tr3,_PowerPCBase(r2)\n");
DoOutput("\taddi\tr4,r1,0x20\n\tlwz\tr0,-298(r3)\n\tmtlr\tr0\n\tblrl\n"
"\tlwz\tr3,0x34(r1)\n\taddi\tr1,r1,0xB0\n\tlwz\tr0,8(r1)\n\tmtlr\tr0\n\tblr\n");
}
if(Flags & FLAG_WOSLIBBASE)
return DoOutput("\t.type\t__%s,@function\n\t.size\t__%s,$-__%s\n\n",
name, name, name);
else
return DoOutput("\t.type\t_%s,@function\n\t.size\t_%s,$-_%s\n\n",
name, name, name);
}
ULONG FuncVBCCWOSCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG i, j = 0, k, l = 0, ofs, pos, count;
ULONG *data;
struct ClibData *cd = 0;
data = (ULONG *) tempbuf;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG))
return 1;
if((flags & FUNCFLAG_TAG) && !(ap->Flags & AMIPRAGFLAG_PPC) && !(cd = GetClibFunc(name, ap, flags)))
return 1;
if((ap->Flags & AMIPRAGFLAG_PPC) && !BaseName &&
((ap->Flags & (AMIPRAGFLAG_PPC0|AMIPRAGFLAG_PPC2)) || !(Flags & FLAG_WOSLIBBASE)))
{
DoError(ERR_MISSING_BASENAME, ap->Line);
return 1;
}
Flags |= FLAG_DONE; /* We did something */
if(Flags & FLAG_WOSLIBBASE)
{
i = strlen(name)+1;
data[0] = HUNK_UNIT; data[1] = (i + 3)>>2;
DoOutputDirect(data, 8);
DoOutputDirect("_", 1);
DoOutputDirect(name, i-1);
}
else
{
i = strlen(name);
data[0] = HUNK_UNIT; data[1] = (i + 3)>>2;
DoOutputDirect(data, 8);
DoOutputDirect(name, i);
}
DoOutputDirect("\0\0\0", (data[1]<<2)-i);
data[0] = HUNK_NAME;
data[1] = 2;
DoOutputDirect(data, 8);
DoOutputDirect(".text\0\0\0", 8);
data[0] = HUNK_PPC_CODE;
pos = 2;
if(ap->Flags & AMIPRAGFLAG_PPC2)
{
data[pos++] = 0x90410014; /* stw r2,20(r1) */
data[pos++] = 0x7C0802A6; /* mflr r0 = mfspr r0,8 = get link register */
data[pos++] = 0x90010010; /* stw r0,16(r1) */
l = pos-2;
data[pos++] = 0x80420000; /* lwz r2,BaseName(r2) */
data[pos++] = 0x80030000 - ap->Bias; /* lwz r0,-ap->Bias(r2) */
data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
data[pos++] = 0x4E800021; /* blrl = bclrl 20,0 = jump */
data[pos++] = 0x80010010; /* lwz r0,16(r1) */
data[pos++] = 0x80410014; /* lwz r2,20(r1) */
data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
data[pos++] = 0x4E800020; /* blr = bclr 20,0 = jump */
}
else if(ap->Flags & AMIPRAGFLAG_PPC0)
{
l = pos-2;
data[pos++] = 0x81620000; /* lwz r11,BaseName(r2) */
data[pos++] = 0x800C0000 - ap->Bias; /* lwz r0,-ap->Bias(r11) */
data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = store link register */
data[pos++] = 0x4E800021; /* blrl = bclrl 20,0 = jump */
}
else if(ap->Flags & AMIPRAGFLAG_PPC)
{
count = ap->NumArgs;
if(Flags & FLAG_WOSLIBBASE) /* LibBase already in r3 */
{
/* init stack frame */
i = (count <= 8) ? 32 : ((56+(count-8)*8+15)&~15); /* stksize */
data[pos++] = 0x7C0802A6; /* mflr r0 = mfspr r0,8 = get link register */
data[pos++] = 0x90010008; /* stw r0,8(r1) */
data[pos++] = 0x94220000 - i; /* stwu r1,-i(r1) */
if(count > 8)
{
/* extra arguments must be passed on the stack */
k = 32-(count-8); /* firstreg */
data[pos++] = 0xBC010000 + (k << 21) + (56+(count-8)*4); /* stmw rk,X(r1) */
data[pos++] = 0xB8010000 + (k << 21) + (i+56); /* lmw rk,Y(r1) */
if(flags & FUNCFLAG_TAG)
data[pos++] = 0x3BE10000 + (i+20+count*4); /* addi r31,r1,X */
data[pos++] = 0xBC010038 + (k << 21); /* stmw rk,56(r1) */
}
else if(flags & FUNCFLAG_TAG)
{
data[pos++] = 0x38010000 + ((count+3)<<21) + (i+20+count*4); /* addi rX,r1,Y */
--count;
}
}
else /* Args must be shifted! */
{
/* init stack frame */
i = (count < 8) ? 32 : ((56+(count-7)*8+15)&~15); /* stksize */
data[pos++] = 0x7C0802A6; /* mflr r0 = mfspr r0,8 = get link register */
data[pos++] = 0x90010008; /* stw r0,8(r1) */
data[pos++] = 0x94220000 - i; /* stwu r1,-i(r1) */
if(count > 7)
{
/* extra arguments must be passed on the stack */
if(count == 8)
{
/* special case: move 8th argument into stack frame */
if(flags & FUNCFLAG_TAG)
data[pos++] = 0x39410000 + (i+20+count*4); /* addi r10,r1,X */
data[pos++] = 0x91410038; /* stw r10,56(r1) */
}
else
{
k = 32-(count-7); /* firstreg */
data[pos++] = 0xBC010000 + (k << 21) + (56+(count-7)*4); /* stmw rk,X(r1) */
data[pos++] = 0x7D405378 + (k<<16); /* mr rk,r10 = or rk,r10,r10 */
data[pos++] = 0xB8010000 + ((k+1) << 21) + (i+56); /* lmw rk,Y(r1) */
if(flags & FUNCFLAG_TAG)
data[pos++] = 0x3BE10000 + (i+20+count*4); /* addi r31,r1,X */
data[pos++] = 0xBC010038 + (k << 21); /* stmw rk,56(r1) */
}
}
else if(flags & FUNCFLAG_TAG)
{
data[pos++] = 0x38010000 + ((count+3)<<21) + (i+20+count*4); /* addi rX,r1,Y */
--count;
}
/* shift all arguments into their following register */
for(k=(count<8)?count:7; k > 0; --k)
data[pos++] = 0x7C000378 + ((3+k)<<16) + ((2+k)<<21) + ((2+k)<<11); /* mr rX,rY = or rX,rY,rY */
/* load library base and LVO, then call LVO via LR */
l = pos-2;
data[pos++] =0x80620000; /* lwz r3,BaseName(r2) */
}
/* call LVO */
data[pos++] = 0x80040000 - (ap->Bias-2); /* lwz r0,-(ap->Bias-2)(r3) */
data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
data[pos++] = 0x4E800021; /* blrl = bclrl 20,0 = jump */
/* cleanup stack frame and return */
if(count > 8)
{
k = Flags & FLAG_WOSLIBBASE ? 8 : 7; /* restore saved regs */
data[pos++] = 0xB8010000 + ((32-(count-k))<<21) + (56+(count-k)*4); /* lmw rX,Y(r1) */
}
data[pos++] = 0x38210000 + i; /* addi r1,r1,i */
data[pos++] = 0x80010008; /* lwz r0,8(r1) */
data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
data[pos++] = 0x4E800020; /* blr = bclr 20,0 = jump */
}
else
{
data[pos++] = 0x7C0802A6; /* mflr r0 = mfspr r0,8 = get link register */
data[pos++] = 0x90010008; /* stw r0,8(r1) = save link register in 8(r1) */
data[pos++] = 0x9421FF50; /* stwu r1,-0xB0(r1) = store word from r1 in -0xB0(r1) and update r1 */
data[pos++] = 0x39600000; /* li r11,0 = addi r11,r0,0 = clear r11 */
data[pos++] = 0x91610028; /* stwu r11,0x28(r1) = clear PP_Flags */
data[pos++] = 0x9161002C; /* stwu r11,0x2C(r1) = clear PP_Stack */
data[pos++] = 0x91610030; /* stwu r11,0x30(r1) = clear PP_StackSize */
if(Flags & FLAG_WOSLIBBASE)
{
data[pos++] = 0x39610000 - ap->Bias; /* li r11,ap->Bias */
data[pos++] = 0x90810020; /* stw r4,0x20(r1) = set PP_Code to Librarybase */
data[pos++] = 0x91610024; /* stw r11,0x24(r1) = set PP_Offset to Bias value */
data[pos++] = 0x9081006C; /* stw r4,0x6C(r1) = set A6 register */
}
else if(!BaseName)
{
data[pos++] = 0x39610000 -ap->Bias; /* li r11,ap->Bias */
data[pos++] = 0x91610024; /* stw r11,0x24(r1) = set PP_Offset to Bias value */
}
else
{
l = pos-2;
data[pos++] = 0x80020000; /* lwz r0,BaseName(r2) --> 16BIT RELOC! */
data[pos++] = 0x39610000 - ap->Bias; /* li r11,ap->Bias */
data[pos++] = 0x90010020; /* stw r0,0x20(r1) = set PP_Code to Librarybase */
data[pos++] = 0x91610024; /* stw r11,0x24(r1) = set PP_Offset to Bias value */
data[pos++] = 0x9001006C; /* stw r4,0x6C(r1) = set A6 register */
}
ofs = Flags & FLAG_WOSLIBBASE ? 2 : 0;
k = ap->NumArgs - (flags & FUNCFLAG_TAG ? 1 : 0);
for(i = 0; i < k; ++i)
{
j = 0x34+4*ap->Args[i].ArgReg; /* PP_Regs offset */
if(i + ofs <= 7)
{
if(ap->Args[i].ArgReg == REG_A6)
data[pos++] = 0x90010020 + ((i+3+ofs)<<21); /* stw rX,0x20(r1) */
data[pos++] = 0x90010000 + ((i+3+ofs)<<21) + j; /* stw rX,j(r1) */
}
else
{
data[pos++] = 0x81610000 + ((i+1+ofs)*4+0xC4); /* lwz r11,X(r1) = get data from stack */
if(ap->Args[i].ArgReg == REG_A6)
data[pos++] = 0x91610020; /* stw r11,0x20(r1) */
data[pos++] = 0x91610000 + j; /* stw r11,j(r1) */
}
}
if(flags & FUNCFLAG_TAG)
{
j = (ap->NumArgs+ofs)*4+0xC4;
if((i+ofs) <= 7 && cd->Args[i].Type != CPP_TYPE_VARARGS)
data[pos++] = 0x90010000 + ((i+3+ofs)<<21) + j; /* stw rX,j(r1) */
data[pos++] = 0x39610000 + j; /* addi r11,r1,j */
data[pos++] = 0x91610000 + (0x34+4*ap->Args[i].ArgReg); /* stw r11,X(r1) */
}
if(!(Flags & FLAG_WOSLIBBASE))
{
j = pos - 2; /* store 16BIT reloc offset */
data[pos++] = 0x80620000; /* lwz r3,_PowerPCBase(r2) = get librarybase */
}
data[pos++] = 0x38810020; /* addi r4,r1,0x20 = {r4 := 0x20(r1)} */
data[pos++] = 0x8003FED6; /* lwz r0,-298(r3) = load jumpin base */
data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = store link register */
data[pos++] = 0x4E800021; /* blrl = bclrl 20,0 = jump */
data[pos++] = 0x80610034; /* lwz r3,0x34(r1) = get result D0 */
data[pos++] = 0x382100B0; /* addi r1,r1,0xB0 = free PRCArgs structure */
data[pos++] = 0x80010008; /* lwz r0,8(r1) = get old link register */
data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
data[pos++] = 0x4E800020; /* blr = bclr 20,0 = jump back */
}
data[1] = pos-2;
data[pos++] = HUNK_EXT;
DoOutputDirect(data, pos*4);
if(Flags & FLAG_WOSLIBBASE)
{
if(ap->Flags & (AMIPRAGFLAG_PPC0|AMIPRAGFLAG_PPC2))
{
i = strlen(BaseName);
data[0] = (EXT_DEXT16 << 24) + ((i + 1 + 3)>>2);
data[1] = ('_' << 24);
DoOutputDirect(data, 5);
DoOutputDirect(BaseName, i++);
DoOutputDirect("\0\0\0", ((i+3)&(~3))-i);
data[0] = 1;
data[1] = l*4+2; /* l holds base reference position */
DoOutputDirect(data, 8);
}
OutputXDEF("__%s", name);
}
else
{
if(BaseName)
{
i = strlen(BaseName);
data[0] = (EXT_DEXT16 << 24) + ((i + 1 + 3)>>2);
data[1] = ('_' << 24);
DoOutputDirect(data, 5);
DoOutputDirect(BaseName, i++);
DoOutputDirect("\0\0\0", ((i+3)&(~3))-i);
data[0] = 1;
data[1] = l*4+2; /* l holds base reference position */
DoOutputDirect(data, 8);
}
if(!(ap->Flags & AMIPRAGFLAG_PPC))
{
data[0] = (EXT_DEXT16 << 24) + (12>>2);
DoOutputDirect(data, 4);
DoOutputDirect("_PowerPCBase", 12);
data[0] = 1;
data[1] = j*4+2; /* j holds PPC base reference position */
DoOutputDirect(data, 8);
}
OutputXDEF("_%s", name);
}
data[0] = 0;
DoOutputDirect(data, 4);
if(!(Flags & FLAG_NOSYMBOL))
{
data[0] = HUNK_SYMBOL;
DoOutputDirect(data, 4);
if(Flags & FLAG_WOSLIBBASE)
OutputSYMBOL("__%s", name);
else
OutputSYMBOL("_%s", name);
data[0] = 0;
DoOutputDirect(data, 4);
}
data[0] = HUNK_END;
return DoOutputDirect(data, 4);
}
ULONG FuncVBCCPUPText(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG i;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE;
if(Flags & FLAG_ASMSECTION)
DoOutput("\t.section %s,\"cr\"\n", name);
DoOutput("\t.text\n");
if(BaseName)
DoOutput("\t.global %s\n", BaseName);
DoOutput("\t.global PPCCallOS\n\t.global %s\n"
"\t.align\t3\n%s:\n",name, name);
if(flags & FUNCFLAG_TAG)
{
/* Hack the stack-frame for varargs.
Build stack-frame, but save LR in our own stack-frame,
because we have to overwrite the lower 8 bytes of the
caller's frame. */
DoOutput("\tstwu\tr1,-128(r1)\n\tmflr\tr11\n\tstw\tr11,100(r1)\n");
/* Save the caller's saved SP in our own stack-frame. */
DoOutput("\tlwz\tr11,128(r1)\n\tstw\tr11,96(r1)\n");
/* Store r3-r8 at the top of our stack-frame and r9-r10
at the low 8 bytes of the caller's frame. This way all
arguments will reside in one continuous area. */
for(i=3+ap->NumArgs-1; i <= 10; ++i)
DoOutput("\tstw\tr%ld,%ld(r1)\n", i, 104+4*(i-3));
}
else
DoOutput("\tstwu\tr1,-96(r1)\n\tmflr\tr11\n\tstw\tr11,100(r1)\n");
for(i = 0; i < ap->NumArgs; ++i)
{
if(!(flags & FUNCFLAG_TAG) || i < ap->NumArgs-1)
{
if(i <= 7)
DoOutput("\tstw\tr%ld,",i+3);
else
DoOutput("\tlwz\tr11,%ld(r1)\n\tstw\tr11,",100+(i+1-8)*4);
}
else
DoOutput("\taddi\tr11,r1,%ld\n\tstw\tr11,",100+ap->NumArgs*4);
DoOutput("%ld(r1)\n",36+4*ap->Args[i].ArgReg);
}
/* Now place the real function call */
DoOutput("\tli\tr11,-%ld\n\tstw\tr11,8(r1)\n" /* store offset in Chaos->caos_Un.Offset */
"\tli\tr11,1\n\tstw\tr11,12(r1)\n\tstw\tr11,24(r1)\n", ap->Bias);
/* set M68kCacheMode and PPCCacheMode to IF_CACHEFLUSHALL */
if(BaseName)
{
if(Flags & FLAG_SMALLDATA)
DoOutput("\tlwz\tr11,%s@sdarx(r13)\n",BaseName);
else
DoOutput("\tlis\tr11,%s@ha\n\tlwz\tr11,%s@l(r11)\n",
BaseName,BaseName);
DoOutput("\tstw\tr11,92(r1)\n"); /* store basepointer in A6 */
}
DoOutput("\taddi\tr3,r1,8\n\tbl\tPPCCallOS\n");
if(flags & FUNCFLAG_TAG) /* Varargs. Rebuild the caller's stack-frame. */
DoOutput("\tlwz\tr11,96(r1)\n\tstw\tr11,128(r1)\n"
"\tlwz\tr11,100(r1)\n\tmtlr\tr11\n\taddi\tr1,r1,128\n");
else
DoOutput("\tlwz\tr11,100(r1)\n\tmtlr\tr11\n\taddi\tr1,r1,96\n");
return DoOutput("\tblr\n\n");
}
ULONG FuncVBCCPUPCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
{
ULONG i, j=0, k, *data, pos;
struct Elf32_Shdr *esh;
struct Elf32_Ehdr *eeh;
struct Elf32_Sym *esym;
struct Elf32_Rela *erel;
UBYTE size[10];
struct ArHeader arh;
data = (ULONG *) tempbuf;
if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_PPC))
return 1;
Flags |= FLAG_DONE;
memset((STRPTR)tempbuf,0,TEMPSIZE); /* clear all entries */
memset(&arh, ' ', sizeof(struct ArHeader));
if((i = strlen(name)) > 15-3)
{
sprintf(arh.ar_name, "%.5s__%s.o/", name, name+i-5);
arh.ar_name[15] = ' ';
}
else
{
sprintf(arh.ar_name, "%s.o/", name);
arh.ar_name[i+3] = ' ';
}
CopyMem("942836400", arh.ar_time, 9); /* 17.11.1999 12:00:00 */
arh.ar_uid[0] = arh.ar_gid[0] = arh.ar_mode[1] =
arh.ar_mode[2] = '0';
arh.ar_mode[0] = '6';
arh.ar_fmag[0] = 96;
arh.ar_fmag[1] = '\n';
eeh = (struct Elf32_Ehdr *) data;
eeh->e_ident[EI_MAG0] = 0x7F;
eeh->e_ident[EI_MAG1] = 'E';
eeh->e_ident[EI_MAG2] = 'L';
eeh->e_ident[EI_MAG3] = 'F';
eeh->e_ident[EI_CLASS] = ELFCLASS32;
eeh->e_ident[EI_DATA] = ELFDATA2MSB;
eeh->e_ident[EI_VERSION] = EV_CURRENT;
eeh->e_type = ET_REL;
eeh->e_machine = EM_POWERPC;
eeh->e_version = EV_CURRENT;
eeh->e_ehsize = sizeof(struct Elf32_Ehdr);
eeh->e_shentsize = sizeof(struct Elf32_Shdr);
eeh->e_shnum = 6;
eeh->e_shstrndx = 3; /* fourth table is string table */
pos = (sizeof(struct Elf32_Ehdr)>>2);
if(flags & FUNCFLAG_TAG)
{
/* Hack the stack-frame for varargs.
Build stack-frame, but save LR in our own stack-frame,
because we have to overwrite the lower 8 bytes of the
caller's frame. */
data[pos++] = 0x9421FF80; /* stwu r1,-128(r1) */
data[pos++] = 0x7D6802A6; /* mflr r11 = mfspr r11,8 = get link register */
data[pos++] = 0x91610064; /* stw r11,100(r1) */
/* Save the caller's saved SP in our own stack-frame. */
data[pos++] = 0x81610080; /* lwz r11,128(r1) */
data[pos++] = 0x91610060; /* stw r11,96(r1) */
/* Store r3-r8 at the top of our stack-frame and r9-r10
at the low 8 bytes of the caller's frame. This way all
arguments will reside in one continuous area. */
for(i=3+ap->NumArgs-1; i <= 10; ++i)
data[pos++] = 0x90010000 + (i<<21) + (104+4*(i-3)); /* stw rX,Y(r1) */
}
else
{
data[pos++] = 0x9421FFA0; /* stwu r1,-96(r1) */
data[pos++] = 0x7D6802A6; /* mflr r11 = mfspr r11,8 = get link register */
data[pos++] = 0x91610064; /* stw r11,100(r1) */
}
for(i = 0; i < ap->NumArgs; ++i)
{
j = 36+4*ap->Args[i].ArgReg;
if(!(flags & FUNCFLAG_TAG) || i < ap->NumArgs-1)
{
if(i <= 7)
data[pos++] = 0x90010000 + ((i+3)<<21) + j; /* stw rX,j(r1) */
else
{
data[pos++] = 0x81610000 + (100+(i+1-8)*4); /* lwz r11,X(r1) = get data from stack */
data[pos++] = 0x91610000 + j; /* stw r11,j(r1) */
}
}
else
{
data[pos++] = 0x39610000 + (100+ap->NumArgs*4); /* addi r11,r1,X */
data[pos++] = 0x91610000 + j; /* stw r11,X(r1) */
}
}
/* Now place the real function call */
data[pos++] = 0x39610000 - ap->Bias; /* li r11,-(ap->Bias) = addi r11,0,-ap->Bias */
data[pos++] = 0x91610008; /* stw r11,8(r1) */
data[pos++] = 0x39600001; /* li r11,1 = addi r11,0,1 = get IF_CACHEFLUSHALL */
data[pos++] = 0x9161000C; /* stw r11,12(r1) = set M68kCacheMode */
data[pos++] = 0x91610018; /* stw r11,24(r1) = set PPCCacheMode */
if(BaseName)
{
if(Flags & FLAG_SMALLDATA)
{
j = pos<<2; /* store reloc offset */
data[pos++] = 0x816D0000; /* lwz r11,BaseName@sdarx(r13) */
}
else
{
j = pos<<2; /* store reloc offset */
data[pos++] = 0x3D600000; /* lis r11,BaseName@ha = addis r11,0,BaseName@ha */
data[pos++] = 0x816B0000; /* lwz r11,BaseName@l(r11) */
}
data[pos++] = 0x9161005C; /* stw r11,92(r1) */
}
data[pos++] = 0x38610008; /* addi r3,r1,8 */
k = pos<<2; /* store reloc offset */
data[pos++] = 0x48000001; /* bl PPCCallOS */
if(flags & FUNCFLAG_TAG) /* Varargs. Rebuild the caller's stack-frame. */
{
data[pos++] = 0x81610060; /* lwz r11,96(r1) */
data[pos++] = 0x91610080; /* stw r11,128(r1) */
data[pos++] = 0x81610064; /* lwz r11,100(r1) */
data[pos++] = 0x7D6803A6; /* mtlr r11 = mtspr 8,r11 = restore link register */
data[pos++] = 0x38210080; /* addi r1,r1,128 */
}
else
{
data[pos++] = 0x81610064; /* lwz r11,100(r1) */
data[pos++] = 0x7D6803A6; /* mtlr r11 = mtspr 8,r11 = restore link register */
data[pos++] = 0x38210060; /* addi r1,r1,96 */
}
data[pos++] = 0x4E800020; /* blr = bclr 20,0 */
data[pos++] = 0x002E7379; /* 0.sy */
data[pos++] = 0x6D746162; /* mtab */
data[pos++] = 0x002E7374; /* 0.st */
data[pos++] = 0x72746162; /* rtab */
data[pos++] = 0x002E7368; /* 0.sh */
data[pos++] = 0x73747274; /* strt */
data[pos++] = 0x6162002E; /* ab0. */
data[pos++] = 0x74657874; /* text */
data[pos++] = 0x002E7265; /* 0.re */
data[pos++] = 0x6C612E74; /* la.t */
data[pos++] = 0x65787400; /* ext0 */
eeh->e_shoff = (pos<<2);
esh = (struct Elf32_Shdr *) (data+pos);
esh[1].sh_name = 27; /* .text */
esh[1].sh_type = SHT_PROGBITS;
esh[1].sh_flags = SHF_ALLOC|SHF_EXECINSTR;
esh[1].sh_offset = sizeof(struct Elf32_Ehdr);
esh[1].sh_size = ((pos-11)<<2)-sizeof(struct Elf32_Ehdr);
esh[1].sh_addralign = 16;
esh[2].sh_name = 33; /* .rela.text */
esh[2].sh_type = SHT_RELA;
esh[2].sh_link = 4; /* the fifth entry is symbol table */
esh[2].sh_info = 1; /* the second entry is programm data */
esh[2].sh_addralign = 4;
esh[2].sh_entsize = sizeof(struct Elf32_Rela);
esh[3].sh_name = 17; /* .shstrtab */
esh[3].sh_type = SHT_STRTAB;
esh[3].sh_offset = (pos<<2)-44;
esh[3].sh_size = 44;
esh[3].sh_addralign = 1;
esh[4].sh_name = 1; /* .symtab */
esh[4].sh_type = SHT_SYMTAB;
esh[4].sh_link = 5; /* the second entry is our string table */
esh[4].sh_info = 2;
esh[4].sh_addralign = 4;
esh[4].sh_entsize = sizeof(struct Elf32_Sym);
esh[5].sh_name = 9; /* .strtab */
esh[5].sh_type = SHT_STRTAB;
esh[5].sh_addralign = 1;
pos += (sizeof(struct Elf32_Shdr)>>2)*6; /* skip the section headers */
esh[4].sh_offset = (pos << 2);
esym = (struct Elf32_Sym *) (data+pos);
esym[1].st_info = ELF32_ST_INFO(STB_LOCAL,STT_SECTION);
esym[1].st_shndx = 1; /* the second entry is program section! */
pos += BaseName ? 5*((sizeof(struct Elf32_Sym))>>2) : 4*((sizeof(struct Elf32_Sym))>>2);
esh[4].sh_size = (pos<<2)-esh[4].sh_offset;
esh[5].sh_offset = (pos<<2);
esym[2].st_name = 1;
esym[2].st_info = ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE);
esym[2].st_shndx = 1; /* the second entry is program section! */
sprintf(((STRPTR)(data+pos))+1, name); i = 1 + strlen(name) +1;
esym[3].st_name = i;
esym[3].st_info = ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE);
sprintf(((STRPTR)(data+pos))+i, "PPCCallOS"); i += 10;
if(BaseName)
{
esym[4].st_name = i;
esym[4].st_info = ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE);
sprintf(((STRPTR)(data+pos))+i, BaseName); i += strlen(BaseName)+1;
}
pos += (i+3)>>2; /* long aligned! */
esh[5].sh_size = i;
erel = (struct Elf32_Rela *) (data+pos);
esh[2].sh_offset = (pos << 2);
j -= (sizeof(struct Elf32_Ehdr)-2);
k -= sizeof(struct Elf32_Ehdr);
if(!BaseName)
{
erel[0].r_offset = k;
erel[0].r_info = ELF32_R_INFO(3,R_PPC_REL24); /* entry 3, type 10 */
pos += (sizeof(struct Elf32_Rela)>>2);
}
else if(Flags & FLAG_SMALLDATA)
{
erel[0].r_offset = k;
erel[0].r_info = ELF32_R_INFO(3,R_PPC_REL24); /* entry 3, type 10 */
erel[1].r_offset = j;
erel[1].r_info = ELF32_R_INFO(4,R_PPC_SDAREL16); /* entry 3, type 32 */
pos += (2*sizeof(struct Elf32_Rela)>>2);
}
else
{
erel[0].r_offset = k;
erel[0].r_info = ELF32_R_INFO(3,R_PPC_REL24); /* entry 3, type 10 */
erel[1].r_offset = j;
erel[1].r_info = ELF32_R_INFO(4,R_PPC_ADDR16_HA); /* entry 4, type 6 */
erel[2].r_offset = j+4;
erel[2].r_info = ELF32_R_INFO(4,R_PPC_ADDR16_LO); /* entry 4, type 4 */
pos += (3*sizeof(struct Elf32_Rela)>>2);
}
esh[2].sh_size = (pos<<2)-esh[2].sh_offset;
j = pos<<2;
for(i = 9; j; --i) /* make decimal number */
{
size[i] = (j%10)+'0';
j /= 10;
}
for(j = 0; i < 9; ++j)
arh.ar_size[j] = size[++i];
DoOutputDirect(&arh, sizeof(struct ArHeader));
return DoOutputDirect(data, pos*4);
}
ULONG CallFunc(ULONG tagmode, STRPTR comment, FuncType Func)
{
struct Comment *com = 0;
struct AmiPragma *ap;
if(comment)
com = (struct Comment *) Comment.First;
for(ap = (struct AmiPragma *) AmiPragma.First; ap && !CTRL_C;
ap = (struct AmiPragma *) ap->List.Next)
{
if(BaseName && (ap->Flags & AMIPRAGFLAG_A6USE))
{
DoError(ERR_A6_NOT_ALLOWED, ap->Line);
}
else if((ap->Flags & AMIPRAGFLAG_PUBLIC) || (Flags & FLAG_PRIVATE))
{
while(com && com->Bias <= ap->Bias)
{
if(!DoOutput(comment, com->Data))
return 0;
com = (struct Comment *) com->List.Next;
}
#ifdef DEBUG_OLD
Printf("Processing %s\n", ap->FuncName);
#endif
if(tagmode != TAGMODE_TAGS && ap->FuncName &&
!Func(ap, FUNCFLAG_NORMAL, ap->FuncName))
return 0;
if(tagmode && ap->TagName && !Func(ap, FUNCFLAG_TAG, ap->TagName))
return 0;
if(ap->AliasName &&
(((ap->AliasName->Type & FUNCFLAG_TAG) && tagmode) ||
(!(ap->AliasName->Type & FUNCFLAG_TAG) && tagmode != TAGMODE_TAGS)) &&
!Func(ap, FUNCFLAG_ALIAS|ap->AliasName->Type, ap->AliasName->AliasName))
return 0;
}
}
while(com)
{
if(!DoOutput(comment, com->Data))
return 0;
com = (struct Comment *) com->List.Next;
}
return 1;
}
/* ------------------------------------------------------------------ */
LONG AddClibEntry(STRPTR buffer, STRPTR bufend, ULONG linenum)
{
STRPTR buf = buffer;
struct ClibData d, *f;
memset(&d, 0, sizeof(struct ClibData));
if(!GetCPPType(&d.ReturnType, SkipBlanks(buf)))
{
DoError(ERR_UNKNOWN_VARIABLE_TYPE, linenum, 0);
return 0;
}
d.FuncName = SkipBlanks(d.ReturnType.TypeStart+d.ReturnType.FullLength);
while(*(buf++) != '('/*)*/)
;
*(SkipName(d.FuncName)) = 0;
buf = SkipBlanksRet(buf);
while(*buf != /*(*/')' && buf < bufend)
{
if(d.NumArgs == MAXREGPPC+1)
{
DoError(ERR_TO_MUCH_ARGUMENTS, linenum);
return 0;
}
else if(!GetCPPType(&d.Args[d.NumArgs++], buf))
{
DoError(ERR_UNKNOWN_VARIABLE_TYPE, linenum, d.NumArgs);
return 0;
}
buf += d.Args[d.NumArgs-1].FullLength;
while(*buf != ',' && *buf != /*(*/')' && buf < bufend)
++buf;
#ifdef DEBUG_OLD
Printf("Added argument %ld for %s (%ld bytes)\n", d.NumArgs, d.FuncName,
d.Args[d.NumArgs-1].FullLength);
#endif
if(*buf == ',')
buf = SkipBlanksRet(++buf);
}
if(d.NumArgs == 1 && IsCPPType(&d.Args[0], CPP_TYPE_VOID))
d.NumArgs = 0; /* void arguments are no arguments */
if(!(f = (struct ClibData *) AllocListMem(sizeof(struct ClibData))))
return -1;
CopyMem(&d, f, sizeof(struct ClibData));
if(!clibdata)
clibdata = f;
else
{
struct ClibData *e = clibdata;
while(e->Next)
e = e->Next;
e->Next = f;
}
#ifdef DEBUG_OLD
Printf("Added prototype for %s (line %ld, %ld bytes) with %ld args\n",
f->FuncName, linenum, buf-buffer, f->NumArgs);
#endif
return buf-buffer;
}
LONG ScanClibFile(STRPTR buf, STRPTR bufend)
{
STRPTR linestart = buf;
ULONG linenum = 1;
while(buf < bufend && !CTRL_C)
{
if(*buf == '/' && buf[1] == '*')
{
while(buf < bufend && (*buf != '*' || buf[1] != '/'))
{
if(*(buf++) == '\n')
{
++linenum; linestart = buf;
} /* skip comments */
}
}
else if(*buf == '/' && buf[1] == '/')
{
while(buf < bufend && *buf != '\n')
++buf; /* skip line comments */
}
else if(*buf == '\n')
{
linestart = ++buf; ++linenum;
}
else if(*buf == '('/*)*/)
{
LONG i;
if((i = AddClibEntry(linestart, bufend, linenum)) == -1) /* no memory */
return 0;
else if(!i)
{
while(buf < bufend && *buf != '\n')
++buf; /* skip this line */
}
else
{
i -= buf-linestart;
while(buf < bufend && i-- > 0)
{
if(*(buf++) == '\n')
{
linestart = buf;
++linenum;
} /* skip this function */
}
}
}
else
++buf;
} /* while */
return 1;
}
LONG IsCPPType(struct CPP_NameType *data, UBYTE type)
{
if(!data || data->Flags || data->Type != type || data->PointerDepth)
return 0;
return type;
}
LONG GetCPPType(struct CPP_NameType *data, STRPTR start)
{
ULONG ok = 1;
STRPTR u;
data->TypeStart = SkipBlanks(start);
do
{
start = SkipBlanks((u = start));
if(!strncmp("...",start,3))
{
data->Type = CPP_TYPE_VARARGS; return 1;
}
if(CheckKeyword(start, "const", 5) || CheckKeyword(start, "CONST", 5))
{
data->Flags |= CPP_FLAG_CONST; start += 6;
}
else if(CheckKeyword(start, "signed", 6))
start += 7;
else if(CheckKeyword(start, "unsigned", 8))
{
data->Flags |= CPP_FLAG_UNSIGNED; start += 9;
}
else if(CheckKeyword(start, "struct", 6))
{
start = SkipBlanks(start+6);
data->Flags |= CPP_FLAG_STRUCT;
if(*start != '?') /* ? for external types */
{
start = SkipName((data->StructureName = start));
data->StructureLength = start-data->StructureName;
}
else
{
data->StructureLength = 0;
data->StructureName = "";
++start;
}
}
else if(CheckKeyword(start, "union", 5))
{
start = SkipBlanks(start+5);
data->Flags |= CPP_FLAG_UNION;
if(*start != '?') /* ? for external types */
{
start = SkipName((data->StructureName = start));
data->StructureLength = start-data->StructureName;
}
else
{
data->StructureLength = 0;
data->StructureName = "";
++start;
}
}
else if(CheckKeyword(start, "enum", 4))
{
start = SkipBlanks(start+4);
data->Flags |= CPP_FLAG_ENUM;
if(*start != '?') /* ? for external types */
{
start = SkipName((data->StructureName = start));
data->StructureLength = start-data->StructureName;
}
else
{
data->StructureLength = 0;
data->StructureName = "";
++start;
}
}
else if(*start == '*')
{
++start; ++data->PointerDepth;
}
else
{
ULONG i;
for(i = 0; CPP_Field[i].Text; ++i)
{
if(!strncmp(start, CPP_Field[i].Text, CPP_Field[i].Length) &&
(start[CPP_Field[i].Length] == ' ' ||
start[CPP_Field[i].Length] == '\t' ||
start[CPP_Field[i].Length] == '\n' ||
start[CPP_Field[i].Length] == ',' ||
start[CPP_Field[i].Length] == /*(*/')' ||
start[CPP_Field[i].Length] == '('/*)*/ ||
start[CPP_Field[i].Length] == '*'))
{
start += CPP_Field[i].Length;
data->Type = CPP_Field[i].Type;
data->Flags |= CPP_Field[i].Flags;
if(CPP_Field[i].Flags & CPP_FLAG_POINTER)
++data->PointerDepth;
break;
}
}
if(CPP_Field[i].Text)
continue;
else if(extnames)
{
struct CPP_ExternNames *a = extnames;
while(a)
{
i = strlen(a->Type);
if(!strncmp(a->Type, start, i) && !isalnum(start[i]) &&
start[i] != '_')
{
start += i;
data->StructureName = a->NameType.StructureName;
data->FuncArgs = a->NameType.FuncArgs;
data->StructureLength = a->NameType.StructureLength;
data->PointerDepth += a->NameType.PointerDepth;
data->Type = a->NameType.Type;
data->Flags |= a->NameType.Flags;
break;
}
/* check types here */
a = a->Next;
}
if(a)
continue;
}
break;
}
} while(1);
if(start != SkipBlanks(u)) /* we broke the loop after increasing start */
u = start;
data->TypeLength = u - (data->TypeStart);
data->FullLength = data->TypeLength;
u = SkipBlanks(u);
if(*u == '('/*)*/)
{
ok = 0;
u = SkipBlanks(++u);
if(*u == '*')
{
u = SkipBlanks(++u);
if(CheckKeyword(u, "const", 5) || CheckKeyword(u, "CONST", 5))
{
data->Flags |= CPP_FLAG_CONST; u += 6;
}
u = SkipBlanks(SkipName(SkipBlanks(u)));
if(*u == /*(*/')')
{
u = SkipBlanks(++u);
if(*u == '('/*)*/)
{
data->Flags |= CPP_FLAG_FUNCTION;
data->FuncArgs = u;
ok = 1;
u = SkipBlanks(++u);
if(*u == /*(*/')')
data->FuncArgs = 0;
else
{
ULONG d = 0;
while(d || *u != /*(*/')')
{
if(*u == '('/*)*/)
++d;
else if(*u == /*(*/')')
--d;
++u;
}
data->ArgsLength = u+1 - (data->FuncArgs);
}
data->FullLength = u+1 - (data->TypeStart);
}
}
}
}
if(data->PointerDepth)
data->Flags |= CPP_FLAG_POINTER;
if((!data->Type && !data->Flags) || !ok)
return 0;
return 1;
}
struct ClibData *GetClibFunc(STRPTR name, struct AmiPragma *ap, ULONG flags)
{
struct ClibData *d = clibdata;
while(d && strcmp(name, d->FuncName))
d = d->Next;
if(!d)
{
if(!(ap->Flags & AMIPRAGFLAG_NOCLIB))
{
DoError(ERR_PROTOTYPE_MISSING, 0, name);
ap->Flags |= AMIPRAGFLAG_NOCLIB;
}
}
else if(ap->CallArgs != d->NumArgs && (!(flags & FUNCFLAG_TAG) ||
ap->CallArgs+1 != d->NumArgs))
{
if(!(ap->Flags & (AMIPRAGFLAG_CLIBARGCNT|AMIPRAGFLAG_DIDARGWARN)))
{
DoError(ERR_CLIB_ARG_COUNT, 0, name, d->NumArgs, ap->NumArgs);
ap->Flags |= AMIPRAGFLAG_CLIBARGCNT;
}
return 0;
}
return d;
}
LONG CheckKeyword(STRPTR string, STRPTR keyword, LONG size)
{
if(!strncmp(string, keyword, size))
{
string += size;
if(*string == ' ' || *string == '\t' || *string == '\n')
return size;
}
return 0;
}
/* return non zero, when ok, return 0xFFFFFFFF when STRPTR and not flags */
ULONG CopyCPPType(STRPTR buffer, ULONG flag, struct ClibData *cd,
struct AmiArgs *args)
{
/* when flag, then STRPTR is unsigned char * mode, else signed char * */
ULONG ret = 1;
ULONG i, j, k = 0;
for(i = 0; i < cd->NumArgs; ++i)
{
struct CPP_NameType *nt;
nt = &cd->Args[i];
if(!flag && (nt->Flags & CPP_FLAG_STRPTR))
ret = 0xFFFFFFFF;
if(args && (Flags & FLAG_LOCALREG) && (nt->Type != CPP_TYPE_VARARGS))
{
*(buffer++) = CPP_TYPE_REGISTER;
*(buffer++) = args[k].ArgReg + (args[k].ArgReg < 10 ? '0' : 'A'-10);
}
if(nt->Flags & CPP_FLAG_FUNCTION)
{
*(buffer++) = CPP_TYPE_POINTER; *(buffer++) = CPP_TYPE_FUNCTION;
}
for(j = 0; j < nt->PointerDepth; ++j)
*(buffer++) = CPP_TYPE_POINTER;
if(nt->Flags & CPP_FLAG_CONST)
*(buffer++) = CPP_TYPE_CONST;
if((nt->Flags & CPP_FLAG_UNSIGNED) &&
!(flag && (nt->Flags & CPP_FLAG_STRPTR)))
*(buffer++) = CPP_TYPE_UNSIGNED;
if(nt->Flags & CPP_FLAG_ENUM)
*(buffer++) = CPP_TYPE_ENUM;
if(nt->Type)
*(buffer++) = cd->Args[i].Type;
else
{
ULONG i;
sprintf(buffer, "%02ld", (ULONG) nt->StructureLength); buffer += 2;
for(i = 0; i < nt->StructureLength; ++i)
*(buffer++) = nt->StructureName[i];
}
if(nt->Flags & CPP_FLAG_FUNCTION)
{
// if(nt.FuncArgs)
// {
// ******** do something here
// while(*buffer)
// ++buffer;
// }
*(buffer++) = CPP_TYPE_FUNCEND;
}
++k;
if(IsCPPType(nt, CPP_TYPE_DOUBLE)) /* double needs 2 registers */
++k;
}
*(buffer) = 0;
return ret;
}
ULONG OutClibType(struct CPP_NameType *nt, STRPTR txt)
{
DoOutputDirect(nt->TypeStart, nt->TypeLength);
if(!DoOutput((nt->Flags & CPP_FLAG_FUNCTION) ? (txt ? " (*%s)" : " (*)") :
(txt ? " %s" : ""), txt))
return 0;
if(nt->Flags & CPP_FLAG_FUNCTION)
{
if(nt->FuncArgs)
DoOutputDirect(nt->FuncArgs, nt->ArgsLength);
else
return DoOutput("()");
}
return 1;
}
ULONG OutPASCALType(struct CPP_NameType *t, STRPTR txt, ULONG ret)
{
LONG i = t->PointerDepth;
if(t->Flags & CPP_FLAG_CONST)
DoOutput("CONST ");
if(!ret && i == 1 &&
(t->Type == CPP_TYPE_LONG || t->Type == CPP_TYPE_WORD))
{
DoOutput("VAR "); --i;
}
DoOutput("%s : ", txt);
if(!i && t->Flags == CPP_FLAG_BOOLEAN)
return DoOutput("BOOLEAN");
else if(i && t->Type == CPP_TYPE_VOID)
return DoOutput("POINTER");
else if(t->Flags & CPP_FLAG_FUNCTION)
return DoOutput("tPROCEDURE");
while(i--)
DoOutput("p");
if((t->Flags & (CPP_FLAG_STRUCT|CPP_FLAG_UNION)) && t->StructureLength)
{
if(!t->PointerDepth)
DoOutput("t");
return DoOutputDirect(t->StructureName, t->StructureLength);
}
if(t->Flags & CPP_FLAG_UNSIGNED)
{
if(t->Type == CPP_TYPE_LONG)
return DoOutput("CARDINAL");
if(t->Type == CPP_TYPE_WORD)
return DoOutput("WORD");
if(t->Type == CPP_TYPE_BYTE)
return DoOutput(t->PointerDepth == 1 ? "CHAR" : "BYTE");
}
else if(t->Type == CPP_TYPE_WORD)
return DoOutput("INTEGER");
else if(t->Type == CPP_TYPE_BYTE)
return DoOutput("SHORTINT");
return DoOutput("LONGINT");
}
/* ------------------------------------------------------------------ */
ULONG CallPrag(ULONG tagmode, STRPTR type, FuncType Func)
{
if(type)
if((*type && !DoOutput("#if%s\n", type)) ||
!(CallFunc(tagmode, tagmode ? 0 : "/%s */\n", Func)) ||
(*type && !DoOutput("#endif\n")) || CTRL_C)
return 0;
return 1;
}
ULONG CreatePragmaFile(STRPTR amicall, STRPTR libcall, STRPTR amitags,
STRPTR libtags, ULONG mode)
{
switch(mode)
{
case PRAGMODE_PRAGLIB: DoOutput("#ifndef _INCLUDE_PRAGMA_%s_LIB_H\n"
"#define _INCLUDE_PRAGMA_%s_LIB_H\n", ShortBaseNameUpper,
ShortBaseNameUpper); break;
case PRAGMODE_PRAGSLIB: DoOutput("#ifndef PRAGMAS_%s_LIB_H\n#define "
"PRAGMAS_%s_LIB_H\n", ShortBaseNameUpper, ShortBaseNameUpper); break;
case PRAGMODE_PRAGSPRAGS: DoOutput("#ifndef PRAGMAS_%s_PRAGMAS_H\n#define "
"PRAGMAS_%s_PRAGMAS_H\n", ShortBaseNameUpper, ShortBaseNameUpper); break;
case PRAGMODE_NONE: break;
default: return 0;
}
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
if(mode != PRAGMODE_NONE && !DoOutput("\n#ifndef CLIB_%s_PROTOS_H\n#include "
"<clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper, ShortBaseName))
return 0;
if((Flags & FLAG_EXTERNC) &&
!DoOutput("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"))
return 0;
if(Flags & FLAG_GNUPRAG)
{
DoOutput("#ifdef " TEXT_GNUC "\n#include <inline/%s.h>\n#endif\n",
ShortBaseName);
Flags |= FLAG_DONE;
}
if(
!CallPrag(TAGMODE_NORMAL, amicall, FuncAMICALL) ||
!CallPrag(TAGMODE_NORMAL, libcall, FuncLIBCALL))
return 0;
if(tagfuncs)
{
if(
!CallPrag(TAGMODE_TAGS, amitags, FuncAMICALL) ||
!CallPrag(TAGMODE_TAGS, libtags, FuncLIBCALL))
return 0;
}
if((Flags & FLAG_EXTERNC) &&
!DoOutput("\n#ifdef __cplusplus\n}\n#endif\n"))
return 0;
switch(mode)
{
case PRAGMODE_PRAGLIB: DoOutput("\n#endif\t/* _INCLUDE_PRAGMA_%s_LIB_H */\n",
ShortBaseNameUpper); break;
case PRAGMODE_PRAGSLIB: DoOutput("\n#endif\t/* PRAGMAS_%s_LIB_H */\n",
ShortBaseNameUpper); break;
case PRAGMODE_PRAGSPRAGS: DoOutput("\n#endif\t/* PRAGMAS_%s_PRAGMA_H */\n",
ShortBaseNameUpper); break;
case PRAGMODE_NONE: break;
default: return 0;
}
return Output_Error;
}
ULONG CreateCSTUBSFile(void)
{
DoOutput("#ifndef _INCLUDE_%s_CSTUBS_H\n#define _INCLUDE_%s_CSTUBS_H\n",
ShortBaseNameUpper, ShortBaseNameUpper);
if(!clibdata)
{
DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
}
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
if(!DoOutput("\n#ifndef CLIB_%s_PROTOS_H\n#include "
"<clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper, ShortBaseName))
return 0;
if(!CallFunc(TAGMODE_TAGS, "/%s */\n", FuncCSTUBS))
return 0;
return DoOutput("#endif\t/* _INCLUDE_%s_CSTUBS_H */\n",
ShortBaseNameUpper);
}
ULONG CreateLVOFile(ULONG mode)
{
STRPTR data = "_LVO_I";
if(mode == 2 || mode == 4)
data = "_LIB_I";
if(!DoOutput("\t\tIFND LIBRARIES_%s%s\nLIBRARIES_%s%s\tSET\t1\n\n",
ShortBaseNameUpper, data, ShortBaseNameUpper, data) ||
(HEADER && (!DoOutput("\n") || !DoOutputDirect(HEADER, headersize))) ||
(mode <= 2 && !CallFunc(TAGMODE_NORMAL, 0, FuncLVOXDEF)) ||
!CallFunc(TAGMODE_NORMAL, "\n%s", FuncLVO) ||
!DoOutput("\n\n\t\tENDC\n") || CTRL_C)
return 0;
return 1;
}
ULONG CreateAsmStubs(ULONG mode, ULONG callmode)
{
/* 1 = Text, 2 = Code */
switch(mode)
{
case 1:
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
if(!(Flags & FLAG_ASMSECTION))
DoOutput("\tSECTION\t\"%s_STUBS\",CODE\n\tXREF\t_%s\n", ShortBaseNameUpper, BaseName);
if(!CallFunc(callmode, "\n%s", FuncAsmText))
return 0;
break;
case 2:
if(!CallFunc(callmode, 0, FuncAsmCode))
return 0;
break;
}
if(CTRL_C)
return 0;
return 1;
}
ULONG CreateProtoFile(ULONG Type)
{
STRPTR str1 = "pragma", str2 = "lib";
DoOutput("#ifndef _PROTO_%s_H\n#define _PROTO_%s_H\n", ShortBaseNameUpper,
ShortBaseNameUpper);
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
switch(Type)
{
case 4: str1 = "pragmas"; /* no break; */
case 2: str2 = "pragmas"; break;
case 3: str1 = "pragmas"; break;
case 5: str1 = "local"; str2 = "loc"; break;
}
DoOutput("\n#ifndef EXEC_TYPES_H\n#include <exec/types.h>\n#endif\n");
if(Type != 5)
DoOutput("#ifndef CLIB_%s_PROTOS_H\n"
"#include <clib/%s_protos.h>\n#endif\n",
ShortBaseNameUpper, ShortBaseName);
if(Type != 8)
{
if(Type >= 6)
{
DoOutput("\n#ifdef " TEXT_GNUC "\n#include <inline/%s.h>\n",
ShortBaseName);
if(Type != 7)
DoOutput("#else");
}
if(Type != 7)
DoOutput("\n#include <%s/%s_%s.h>\n", str1, ShortBaseName, str2);
if(Type >= 6)
DoOutput("#endif\n");
}
if(BaseName)
{
DoOutput("\n#ifndef __NOLIBBASE__\nextern struct %s *", GetBaseType());
if(Type == 7)
DoOutput("\n#ifdef __CONSTLIBBASEDECL__\n__CONSTLIBBASEDECL__\n"
"#endif\n");
DoOutput("%s;\n#endif\n", BaseName);
}
Flags |= FLAG_DONE;
return DoOutput("\n#endif\t/* _PROTO_%s_H */\n", ShortBaseNameUpper);
}
ULONG CreateLocalData(STRPTR to, ULONG callmode, STRPTR clibbuf,
ULONG clibsize)
{
UBYTE a[40];
DoOutput("#ifndef _INCLUDE_PROTO_%s_LOC_H\n"
"#define _INCLUDE_PROTO_%s_LOC_H\n",
ShortBaseNameUpper, ShortBaseNameUpper);
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
DoOutput("\n");
{ /* copies the include lines */
STRPTR str = clibbuf, strend = clibbuf + clibsize;
ULONG i = 0;
/* works too, when no clibbuf, because then following is everytime false */
while(str < strend)
{
if(!strncmp(str, "#include", 8))
{
DoOutput("%s\n",str); ++i;
}
while(*(str++))
;
}
DoOutput(i ? "\n" : "#include <exec/types.h>\n\n");
}
if((Flags & FLAG_EXTERNC) &&
!DoOutput("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"))
return 0;
if(!CallFunc(callmode, "/%s */\n", FuncLocText))
return 0;
if((Flags & FLAG_EXTERNC) &&
!DoOutput("#ifdef __cplusplus\n}\n#endif\n\n"))
return 0;
DoOutput("#endif\t/* _INCLUDE_PROTO_%s_LOC_H */\n", ShortBaseNameUpper);
Out(out.size); /* clears buffer */
sprintf(a, "%s_loc.lib", ShortBaseName);
if(!CloseDest(to) || !(out.file = Open(a, MODE_NEWFILE)))
return 0;
CallFunc(callmode, 0, FuncLocCode);
return CloseDest(a);
}
ULONG CreateInline(ULONG mode, ULONG callmode)
{
if(!clibdata)
{
DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
}
DoOutput("#ifndef _%sINLINE_%s_H\n#define _%sINLINE_%s_H\n",
Flags & FLAG_POWERUP ? "PPC" : "", ShortBaseNameUpper,
Flags & FLAG_POWERUP ? "PPC" : "", ShortBaseNameUpper);
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
DoOutput("\n");
if(mode)
{
if(Flags & FLAG_POWERUP)
DoOutput("#ifndef __PPCINLINE_STUB_H\n"
"#include <powerup/ppcinline/stubs.h>\n#endif\n\n");
else
DoOutput("#ifndef __INLINE_STUB_H\n"
"#include <inline/stubs.h>\n#endif\n\n");
if(mode == 2)
Flags |= FLAG_INLINESTUB;
}
else
{
if(Flags & FLAG_POWERUP)
DoOutput("#ifndef __PPCINLINE_MACROS_H\n"
"#include <powerup/ppcinline/macros.h>\n#endif\n\n");
else
DoOutput("#ifndef __INLINE_MACROS_H\n"
"#include <inline/macros.h>\n#endif\n\n");
Flags |= FLAG_INLINENEW;
}
if(BaseName)
{
if(mode)
DoOutput("#ifndef BASE_EXT_DECL\n#define BASE_EXT_DECL\n"
"#define BASE_EXT_DECL0 extern struct %s *%s;\n#endif\n"
"#ifndef BASE_PAR_DECL\n#define BASE_PAR_DECL\n"
"#define BASE_PAR_DECL0 void\n#endif\n"
"#ifndef BASE_NAME\n#define BASE_NAME %s\n#endif\n\n"
"BASE_EXT_DECL0\n\n", GetBaseType(), BaseName, BaseName);
else
DoOutput("#ifndef %s_BASE_NAME\n#define %s_BASE_NAME %s\n#endif\n\n",
ShortBaseNameUpper, ShortBaseNameUpper, BaseName);
}
if(!CallFunc(callmode, "/%s */\n", FuncInline))
return 0;
if(mode && BaseName)
DoOutput("#undef BASE_EXT_DECL\n#undef BASE_EXT_DECL0\n"
"#undef BASE_PAR_DECL\n#undef BASE_PAR_DECL0\n#undef BASE_NAME\n\n");
return DoOutput("#endif /* _%sINLINE_%s_H */\n",
Flags & FLAG_POWERUP ? "PPC" : "", ShortBaseNameUpper);
}
ULONG CreateSASPowerUP(ULONG callmode)
{
DoOutput("#ifndef _PPCPRAGMA_%s_H\n#define _PPCPRAGMA_%s_H\n",
ShortBaseNameUpper, ShortBaseNameUpper);
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
DoOutput("\n#ifdef __GNUC__\n"
"#ifndef _PPCINLINE__%s_H\n"
"#include <powerup/ppcinline/%s.h>\n"
"#endif\n"
"#else\n\n"
"#ifndef POWERUP_PPCLIB_INTERFACE_H\n"
"#include <powerup/ppclib/interface.h>\n"
"#endif\n\n"
"#ifndef POWERUP_GCCLIB_PROTOS_H\n"
"#include <powerup/gcclib/powerup_protos.h>\n"
"#endif\n\n"
"#ifndef NO_PPCINLINE_STDARG\n"
"#define NO_PPCINLINE_STDARG\n"
"#endif /* SAS-C PPC inlines */\n\n",
ShortBaseNameUpper, ShortBaseName);
if(BaseName)
{
DoOutput("#ifndef %s_BASE_NAME\n#define %s_BASE_NAME %s\n#endif\n\n",
ShortBaseNameUpper, ShortBaseNameUpper, BaseName);
}
if(!CallFunc(callmode, "/%s */\n", FuncPowerUP))
return 0;
return DoOutput("#endif /* SAS-C PPC pragmas */\n"
"#endif /* _PPCPRAGMA_%s_H */\n", ShortBaseNameUpper);
}
ULONG CreateProtoPowerUP(void)
{
DoOutput("#ifndef PPCPROTO_%s_H\n#define PPCPROTO_%s_H\n",
ShortBaseNameUpper, ShortBaseNameUpper);
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
DoOutput("\n#include <clib/%s_protos.h>\n\n#ifdef " TEXT_GNUC "\n"
"#include <powerup/ppcinline/%s.h>\n#else /* SAS-C */\n"
"#include <powerup/ppcpragmas/%s_pragmas.h>\n#endif\n",
ShortBaseName, ShortBaseName, ShortBaseName);
if(BaseName)
{
DoOutput("\n#ifndef __NOLIBBASE__\nextern struct %s *", GetBaseType());
DoOutput("\n#ifdef __CONSTLIBBASEDECL__\n__CONSTLIBBASEDECL__\n"
"#endif\n%s;\n#endif\n", BaseName);
}
Flags |= FLAG_DONE;
return DoOutput("\n#endif\t/* PPCPROTO_%s_H */\n", ShortBaseNameUpper);
}
ULONG CreateFPCUnit(void)
{
if(!clibdata)
{
DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
}
DoOutput("UNIT %s;\n", ShortBaseNameUpper);
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
DoOutput("\nINTERFACE\nUSES Exec;\n\nVAR %s : p%s;\n\n", BaseName,
GetBaseType());
if(!CallFunc(TAGMODE_NORMAL, 0, FuncFPCType))
return 0;
DoOutput("\nIMPLEMENTATION\n\n");
if(!CallFunc(TAGMODE_NORMAL, "(%s *)\n", FuncFPCUnit))
return 0;
return DoOutput("END. (* UNIT %s *)\n", ShortBaseNameUpper);
}
ULONG CreateBMAP(void)
{
return CallFunc(TAGMODE_NORMAL, 0, FuncBMAP);
}
ULONG CreateLVOLib(void)
{
ULONG a[5], i;
i = strlen(ShortBaseNameUpper);
a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
a[3] = (i + 4 + 3)>>2;
DoOutputDirect(a, 16);
DoOutputDirect(ShortBaseNameUpper, i);
DoOutputDirect("_LVO\0\0\0", (a[3]<<2)-i);
a[0] = HUNK_CODE; a[1] = 0; a[2] = HUNK_EXT;
DoOutputDirect(a, 12);
if(!CallFunc(TAGMODE_NORMAL, 0, FuncLVOLib))
return 0;
a[0] = 0; a[1] = HUNK_END;
return DoOutputDirect(a, 8);
}
ULONG CreateVBCCInline(void)
{
if(!clibdata)
{
DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
}
DoOutput("#ifndef _VBCCINLINE_%s_H\n#define _VBCCINLINE_%s_H\n",
ShortBaseNameUpper, ShortBaseNameUpper);
DoOutput("\n#ifndef EXEC_TYPES_H\n#include <exec/types.h>\n#endif\n");
if(HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
DoOutput("\n");
if(!CallFunc(TAGMODE_NORMAL, "/%s */\n", FuncVBCCInline))
return 0;
return DoOutput("#endif /* _VBCCINLINE_%s_H */\n", ShortBaseNameUpper);
}
ULONG CreateVBCC(ULONG mode, ULONG callmode)
{
ULONG res = 0;
if(mode != 2 && mode != 3 && HEADER)
{
DoOutput("\n");
DoOutputDirect(HEADER, headersize);
}
switch(mode)
{
case 4: res = CallFunc(callmode, 0, FuncVBCCPUPText); break;
case 3: Flags |= FLAG_WOSLIBBASE; /* no break! */
case 2: res = CallFunc(callmode, 0, FuncVBCCWOSCode); break;
case 1: Flags |= FLAG_WOSLIBBASE; /* no break! */
case 0: res = CallFunc(callmode, "\n%s", FuncVBCCWOSText); break;
}
return res;
}
ULONG CreateVBCCPUPLib(ULONG callmode)
{
/* output header */
DoOutput("!<arch>\n");
return CallFunc(callmode, 0, FuncVBCCPUPCode);
}
/* ------------------------------------------------------------------ */
ULONG GetName(struct NameList *t, struct ShortListRoot *p, ULONG args)
{
struct NameList *p2 = (struct NameList *) p->First;
struct AmiPragma ap;
ap.FuncName = t->NormName;
ap.NumArgs = 1;
ap.Args[0].ArgName = (args ? "args" : "tags");
if(!MakeTagFunction(&ap))
return 0;
while(p2 && strcmp(p2->PragName, ap.TagName))
p2 = (struct NameList *) p2->List.Next;
if(!p2)
return 0;
t->Type = (args ? NTP_ARGS : NTP_TAGS);
t->PragName = ap.TagName;
RemoveItem(p, (struct ShortList *) p2);
#ifdef DEBUG_OLD
VPrintf("GetName: name matches - %s _ %s\n", &t->NormName);
#endif
return 1;
}
void OptimizeFDData(struct PragData *pd)
{
#ifdef DEBUG_OLD
PutStr("OptimizeFDData\n");
#endif
while(pd && !CTRL_C)
{
if(pd->NumNames > 1)
{
struct ShortListRoot n = {0,0,0}, p = {0,0,0};
struct NameList *t;
while(pd->Name.First) /* sorts in AmiCall and TagCall */
{
t = (struct NameList *) pd->Name.First;
RemoveItem(&pd->Name, (struct ShortList *) t);
AddItem(t->PragName ? &p : &n, (struct ShortList *) t);
}
if(p.First)
{
t = (struct NameList *) n.First;
while(p.First && t)
{
if(!GetName(t, &p, 0))
{
GetName(t, &p, 1);
}
if(t->PragName)
{
struct NameList *t2 = (struct NameList *) t->List.Next;
RemoveItem(&n, (struct ShortList *)t);
AddItem(&pd->Name, (struct ShortList *) t);
t = t2;
}
else
t = (struct NameList *) t->List.Next;
}
while(p.First)
{
if(n.First)
{
t = (struct NameList *) n.First;
t->PragName = ((struct NameList *)(p.First))->PragName;
RemoveItem(&n, (struct ShortList *) t);
#ifdef DEBUG_OLD
VPrintf("OptimizeFDData: names together - %s _ %s\n", &t->NormName);
#endif
t->Type = NTP_UNKNOWN;
}
else
{
ULONG i;
t = (struct NameList *) p.First;
i = strlen(t->PragName);
t->NormName = DupString(t->PragName, i+1);
t->NormName[i++] = 'A';
t->NormName[i] = 0;
t->Type = NTP_TAGS;
#ifdef DEBUG_OLD
VPrintf("OptimizeFDData: NormName created - %s _ %s\n", &t->NormName);
#endif
}
AddItem(&pd->Name, (struct ShortList *) t);
RemoveItem(&p, p.First);
}
}
AddItem(&pd->Name, n.First); /* add left NormNames */
}
pd = (struct PragData *) pd->List.Next;
}
}
ULONG MakeFD(struct PragList *pl)
{
struct PragData *pd = (struct PragData *) pl->Data.First;
ULONG bias;
#ifdef DEBUG_OLD
PutStr("MakeFD\n");
#endif
bias = pd->Bias;
OptimizeFDData(pd);
#ifdef DEBUG_OLD
PutStr("MakeFD: after Optimizing\n");
#endif
DoOutput("##base _%s\n##bias %ld\n##public\n", pl->Basename, bias);
while(pd && !CTRL_C && Output_Error)
{
struct NameList *n = (struct NameList *) pd->Name.First;
if(bias != pd->Bias)
DoOutput("##bias %ld\n", (bias = pd->Bias));
while(n)
{
STRPTR lastpar = "last";
ULONG i;
if(n->Type == NTP_TAGS)
lastpar = "tags";
else if(n->Type == NTP_ARGS)
lastpar = "args";
DoOutput("%s("/*)*/,n->NormName);
if(!pd->NumArgs)
DoOutput(/*(*/")()\n");
else
{
for(i = 0; i < pd->NumArgs-1; ++i)
DoOutput("par%ld,",i+1);
DoOutput(/*(*/"%s)("/*)*/, lastpar);
for(i = 0; i < pd->NumArgs-1; ++i)
DoOutput("%s,", RegNames[pd->ArgReg[i]]);
DoOutput(/*(*/"%s)\n", RegNames[pd->ArgReg[i]]);
if(n->Type == NTP_UNKNOWN)
{
ULONG i;
for(i = 0; n->NormName[i] == n->PragName[i]; ++i)
;
DoOutput("*tagcall");
if(n->NormName[i])
DoOutput("-%s", n->NormName+i);
if(n->PragName[i])
DoOutput("+%s", n->PragName+i);
DoOutput("\n");
}
}
if((n = (struct NameList *) n->List.Next))
DoOutput("##bias %ld\n", pd->Bias);
Flags |= FLAG_DONE;
}
pd = (struct PragData *)pd->List.Next; bias += BIAS_OFFSET;
}
if(CTRL_C)
return 0;
DoOutput("##end\n");
return Output_Error;
}
ULONG AddFDData(struct ShortListRoot *pls, struct FDData *fd)
{
struct NameList *t;
struct PragList *pl = (struct PragList *) pls->First;
struct PragData *pd;
while(pl && strcmp(pl->Basename, fd->Basename))
pl = (struct PragList *) pl->List.Next;
if(!pl)
{
#ifdef DEBUG_OLD
VPrintf("AddFDData: New PragList - %s\n", &fd->Basename);
#endif
if(!(pl = (struct PragList *) NewItem(pls)))
return 100;
pl->Basename = fd->Basename;
pl->Data.Size = sizeof(struct PragData);
AddItem(pls, (struct ShortList *) pl);
}
if((pd = (struct PragData *) pl->Data.First))
{
while(pd->List.Next && ((struct PragData *) pd->List.Next)->Bias
<= fd->Bias)
pd = (struct PragData *) pd->List.Next;
}
if(!pd || pd->Bias != fd->Bias)
{
struct PragData *pd2;
#ifdef DEBUG_OLD
{
ULONG args[2];
args[0] = fd->Bias;
args[1] = fd->NumArgs;
VPrintf("AddFDData: New PragData - %ld, %ld\n", &args);
}
#endif
if(!(pd2 = (struct PragData *) NewItem(&pl->Data)))
return 100;
pd2->Bias = fd->Bias;
CopyMem(fd->ArgReg, pd2->ArgReg, MAXREG);
pd2->NumArgs = fd->NumArgs;
pd2->Name.Size = sizeof(struct NameList);
if(!pd)
AddItem(&pl->Data, (struct ShortList *) pd2);
else if(pd->Bias > fd->Bias) /* Insert at start */
{
pd2->List.Next = pl->Data.First;
pl->Data.First = (struct ShortList *) pd2;
}
else /* Insert the entry */
{
pd2->List.Next = pd->List.Next;
pd->List.Next = (struct ShortList *) pd2;
}
pd = pd2;
}
else
{
ULONG i = fd->NumArgs;
if(fd->NumArgs != pd->NumArgs)
{
#ifdef DEBUG_OLD
Printf("ArgNum %ld != %ld\n", fd->NumArgs, pd->NumArgs);
#endif
return ERR_DIFFERENT_TO_PREVIOUS;
}
while(i--)
{
if(fd->ArgReg[i] != pd->ArgReg[i])
{
#ifdef DEBUG_OLD
Printf("ArgReg %lx != %lx\n", fd->ArgReg[i], pd->ArgReg[i]);
#endif
return ERR_DIFFERENT_TO_PREVIOUS;
}
}
}
t = (struct NameList *) pd->Name.First; /* skips same names */
while(t && strcmp(fd->Name, fd->Mode ? t->PragName : t->NormName))
t = (struct NameList *) t->List.Next;
if(t)
return 0;
if(!(t = (struct NameList *) NewItem(&pd->Name)))
return 100;
if(fd->Mode)
t->PragName = fd->Name;
else
t->NormName = fd->Name;
AddItem(&pd->Name, (struct ShortList *) t);
++(pd->NumNames);
#ifdef DEBUG_OLD
VPrintf("AddFDData: New NameList - %s\n", &fd->Name);
#endif
return 0;
}
UBYTE GetHexValue(UBYTE data)
{
if(data >= 'a')
return (UBYTE) (data - 'a' + 10);
else if(data >= 'A')
return (UBYTE) (data - 'A' + 10);
else
return (UBYTE) (data - '0');
}
UBYTE GetDoubleHexValue(UBYTE *data)
{
return (UBYTE)((GetHexValue(*data)<<4)+GetHexValue(data[1]));
}
ULONG GetLibData(struct FDData *fd)
{
ULONG i;
fd->Name = SkipBlanks(in.pos);
in.pos = SkipName(fd->Name); *(in.pos++) = 0;
in.pos = SkipBlanks(in.pos);
fd->Bias = strtoul(in.pos, 0, 16);
in.pos = SkipName(SkipBlanks(SkipName(in.pos)));
if((fd->NumArgs = GetHexValue(*(--in.pos))) > MAXREGNF - 2)
return ERR_TO_MUCH_ARGUMENTS;
--in.pos; /* skips return register */
for(i = 0; i < fd->NumArgs; ++i)
{
if((fd->ArgReg[i] = GetHexValue(*(--in.pos))) > REG_A5)
return ERR_EXPECTED_REGISTER_NAME;
}
return 0;
}
ULONG GetFlibData(struct FDData *fd)
{
ULONG i;
fd->Name = SkipBlanks(in.pos);
in.pos = SkipName(fd->Name); *(in.pos++) = 0;
in.pos = SkipBlanks(in.pos);
fd->Bias = strtoul(in.pos, 0, 16);
in.pos = SkipName(SkipBlanks(SkipName(in.pos))) - 2;
if((fd->NumArgs = GetDoubleHexValue(in.pos)) > MAXREG-2)
return ERR_TO_MUCH_ARGUMENTS;
in.pos -= 2; /* skips return register */
for(i = 0; i < fd->NumArgs; ++i)
{
in.pos -= 2;
if((fd->ArgReg[i] = GetDoubleHexValue(in.pos)) >= MAXREG)
return ERR_EXPECTED_REGISTER_NAME;
else if(fd->ArgReg[i] >= REG_FP0 && (Flags & FLAG_NOFPU))
return ERR_FLOATARG_NOT_ALLOWED;
}
return 0;
}
ULONG GetAmiData(struct FDData *fd)
{
STRPTR endptr;
in.pos = SkipBlanks(in.pos);
if(*in.pos != '('/*)*/)
return ERR_EXPECTED_OPEN_BRACKET;
fd->Basename = ++in.pos;
in.pos = SkipBlanks(endptr = SkipName(in.pos));
if(*in.pos != ',')
return ERR_EXPECTED_COMMA;
*endptr = 0;
in.pos = SkipBlanks(++in.pos);
if(!strncmp(in.pos, "0x", 2))
fd->Bias = strtoul(in.pos+2, 0, 16);
else
fd->Bias = strtoul(in.pos, 0, 10);
in.pos = SkipBlanks(SkipName(in.pos));
if(*in.pos != ',')
return ERR_EXPECTED_COMMA;
fd->Name = in.pos = SkipBlanks(++in.pos);
in.pos = SkipBlanks(endptr = SkipName(in.pos));
if(*in.pos != '('/*)*/)
return ERR_EXPECTED_OPEN_BRACKET;
*endptr = 0;
in.pos = SkipBlanks(++in.pos);
if(*in.pos == /*(*/')')
return 0;
--in.pos;
while(*in.pos != /*(*/')')
{
ULONG i;
in.pos = SkipBlanks(in.pos+1);
for(i = 0; i < REG_FP0; i++)
if(!strnicmp(RegNames[i], in.pos, 2))
break;
if(i == REG_FP0)
{
for(; i < MAXREG; i++)
if(!strnicmp(RegNames[i], in.pos, 3))
break;
}
if(i == MAXREG)
return ERR_EXPECTED_REGISTER_NAME;
else if(i >= REG_FP0 && (Flags & FLAG_NOFPU))
return ERR_FLOATARG_NOT_ALLOWED;
fd->ArgReg[fd->NumArgs] = i; ++fd->NumArgs;
if(fd->NumArgs > MAXREG-2)
return ERR_TO_MUCH_ARGUMENTS;
in.pos = SkipBlanks(in.pos+(i >= REG_FP0 ? 3 : 2));
if(*in.pos != ',' && *in.pos != /*(*/')')
return ERR_EXPECTED_CLOSE_BRACKET;
}
in.pos = SkipBlanks(in.pos+1);
if(*in.pos != /*(*/')')
return ERR_EXPECTED_CLOSE_BRACKET;
return 0;
}
ULONG CreateFDFile(STRPTR to)
{
struct ShortListRoot pl = {0, 0, sizeof(struct PragList)};
ULONG linenum, err = 0, skip;
for(linenum = 1; !CTRL_C && in.pos < in.buf + in.size; ++linenum)
{
in.pos = SkipBlanks(in.pos);
if(!strncmp("#pragma", in.pos, 7))
{
struct FDData fd;
skip = 0;
memset(&fd, 0, sizeof(struct FDData));
in.pos = SkipBlanks(in.pos+7);
if(!strncmp("tagcall", in.pos, 7))
{
fd.Mode = 1;
in.pos = SkipBlanks(in.pos+7);
if(*in.pos == '(' /*)*/) /* Storm method */
err = GetAmiData(&fd);
else /* SAS method */
{
fd.Basename = in.pos;
in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
err = GetLibData(&fd);
}
}
else if(!strncmp("amicall", in.pos, 7)) /* Storm method */
{
in.pos += 7;
err = GetAmiData(&fd);
}
else if(!strncmp("libcall", in.pos, 7)) /* SAS method */
{
fd.Basename = SkipBlanks(in.pos+7);
in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
err = GetLibData(&fd);
}
else if(!strncmp("flibcall", in.pos, 8)) /* SAS method */
{
fd.Basename = SkipBlanks(in.pos+8);
in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
err = GetFlibData(&fd);
}
else if(!strncmp("syscall", in.pos, 7)) /* SAS method */
{
fd.Basename = "SysBase";
err = GetLibData(&fd);
}
else
skip = 1;
if(err)
DoError(err, linenum);
else if(skip)
;
else if((err = AddFDData(&pl, &fd)))
{
if(err != 100)
DoError(err, linenum);
return 0;
}
}
while(*(in.pos++)) /* jumps to first char of next line */
;
}
if(pl.First && !CTRL_C)
{
struct PragList *p = (struct PragList *) pl.First;
if(!p->List.Next)
{
if(!to)
{
STRPTR text;
ULONG i;
if(ShortBaseName)
{
text = ShortBaseName; i = strlen(text);
}
else
{
text = p->Basename; i = strlen(text)-4;
}
to = DupString(text, i + sizeof(FDFILEEXTENSION) - 1);
CopyMem(FDFILEEXTENSION, to+i, sizeof(FDFILEEXTENSION));
}
if(!(out.file = Open(to, MODE_NEWFILE)))
return 0;
err = MakeFD(p);
CloseDest(to);
if(!err)
return 0;
}
else
{
while(p)
{
ULONG i;
i = strlen(p->Basename) - 4;
to = DupString(p->Basename, i + sizeof(FDFILEEXTENSION) - 1);
CopyMem(FDFILEEXTENSION, to+i, sizeof(FDFILEEXTENSION));
if(!(out.file = Open(to, MODE_NEWFILE)))
return 0;
i = MakeFD(p);
CloseDest(to);
if(!i)
return 0;
p = (struct PragList *) p->List.Next;
}
}
}
if(CTRL_C)
DoError(ERR_USER_ABORT, 0);
return 1;
}
const STRPTR helptext =
"INFILE: the input file which should be used\n"
"SPECIAL: 1 - Aztec compiler (xxx_lib.h, MODE 2, AMICALL)\n"
"\t 2 - DICE compiler (xxx_pragmas.h, MODE 3, LIBCALL)\n"
"\t 3 - SAS compiler (xxx_pragmas.h, MODE 3, LIBCALL,LIBTAGS)\n"
"\t 4 - MAXON compiler (xxx_lib.h, MODE 1, AMICALL)\n"
"\t 5 - STORM compiler (xxx_lib.h, MODE 1, AMITAGS,AMICALL)\n"
"\t 6 - all compilers [default]\n"
"\t 7 - all compilers with pragma to inline redirect for GCC\n"
"\t 8 - pragma to inline redirect for GCC\n"
"\t10 - stub-functions for C - C text\n"
"\t11 - stub-functions for C - assembler text\n"
"\t12 - stub-functions for C - link library\n"
"\t13 - defines and link library for local library base (register call)\n"
"\t14 - defines and link library for local library base (stack call)\n"
"\t15 - stub-functions for Pascal - assembler text\n"
"\t16 - stub-functions for Pascal - link library\n"
"\t17 - BMAP file for AmigaBASIC and MaxonBASIC\n"
"\t20 - assembler lvo _lvo.i file\n"
"\t21 - assembler lvo _lib.i file\n"
"\t22 - assembler lvo _lvo.i file no XDEF\n"
"\t23 - assembler lvo _lib.i file no XDEF\n"
"\t24 - assembler lvo link library\n"
"\t30 - proto file with pragma/..._lib.h call\n"
"\t31 - proto file with pragma/..._pragmas.h call\n"
"\t32 - proto file with pragmas/..._lib.h call\n"
"\t33 - proto file with pragmas/..._pragmas.h call\n"
"\t34 - proto file with local/..._loc.h call\n"
"\t35 - proto file for all compilers\n"
"\t36 - proto file for GNU-C compiler only\n"
"\t37 - proto file without lib definitions\n"
"\t40 - GCC inline file (preprocessor based)\n"
"\t41 - GCC inline file (old type - inline based)\n"
"\t42 - GCC inline file (library stubs)\n"
"\t50 - GCC inline files for PowerUP (preprocessor based)\n"
"\t51 - GCC inline files for PowerUP (old type - inline based)\n"
"\t52 - GCC inline files for PowerUP (library stubs)\n"
"\t53 - SAS-C include file for PowerUP\n"
"\t54 - Proto file for PowerUP\n"
"\t60 - FPC pascal unit text\n"
"\t70 - VBCC inline files\n"
"\t71 - VBCC WOS stub-functions - assembler text\n"
"\t72 - VBCC WOS stub-functions - assembler text (libbase)\n"
"\t73 - VBCC WOS stub-functions - link library\n"
"\t74 - VBCC WOS stub-functions - link library (libbase)\n"
"\t75 - VBCC PowerUP stub-functions - assembler text\n"
"\t76 - VBCC PowerUP stub-functions - link library\n"
" 200 - FD file (source is a pragma file!)\n"
"MODE:\t SPECIAL 1-7,AMICALL,LIBCALL,AMITAGS,LIBTAGS:\n"
"\t 1 - _INCLUDE_PRAGMA_..._LIB_H definition method [default]\n"
"\t 2 - _PRAGMAS_..._LIB_H definition method\n"
"\t 3 - _PRAGMAS_..._PRAGMAS_H definition method\n"
"\t 4 - no definition\n"
"\t SPECIAL 11-14,40-42,50-53,71-76:\n"
"\t 1 - all functions, normal interface\n"
"\t 2 - only tag-functions, tagcall interface\n"
"\t 3 - all functions, normal and tagcall interface [default]\n"
"TO:\t the destination directory (self creation of filename) or\n"
"\t the destination file\n"
"CLIB: name of the prototypes file in clib directory\n"
"HEADER: inserts given file into header of created file (\"\" is scan)\n"
"The following four need a string as an argument. This string is used to set\n"
"a #if<given string> before the set method.\n"
"AMICALL: creates amicall pragmas\n"
"LIBCALL: creates libcall pragmas\n"
"AMITAGS: creates tagcall pragmas (amicall like method (StormC++))\n"
"LIBTAGS: creates tagcall pragmas (libcall like method (SAS C))\n"
"Switches:\n"
"COMMENT: copy comments found in FD file\n"
"EXTERNC: add a #ifdef __cplusplus ... statement to pragma file\n"
"FPUONLY: work only with functions using FPU register arguments\n"
"NEWSYNTAX: uses new Motorola syntax for asm files\n"
"NOFPU: disable usage of FPU register arguments\n"
"NOPPC: disable usage of PPC-ABI functions\n"
"NOSYMBOL: prevents creation of SYMBOL hunks for link libraries\n"
"OPT040: optimize for 68040, do not use MOVEM for stubs\n"
"PPCONLY: only use PPC-ABI functions\n"
"PRIVATE: includes private declared functions\n"
"SECTION: add section statements to asm texts\n"
"SMALLDATA: generate small data link libraries or assembler text\n"
"SORTED: sort generated files by name and not by bias value\n"
"STORMFD: converts FD files of strange StormC++ format\n"
"USESYSCALL: uses syscall pragma instead of libcall SysBase\n";
void main(void)
{
ULONG mode = 0, pragmode = PRAGMODE_PRAGLIB, callmode = TAGMODE_BOTH;
ULONG spec = 0; /* for default setting I need a ULONG var to get a pointer */
UBYTE filename[255]; /* needed for filename */
struct Args args;
STRPTR clibbuf = 0;
ULONG clibsize = 0;
#ifdef __SASC /* with __MAXON__ this is done automatic by my StartUp */
TestOS;
#endif
memset(&args, 0, sizeof(struct Args)); /* initialize */
args.SPECIAL = &spec;
if(!(rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
End(RETURN_FAIL);
rda->RDA_ExtHelp = helptext;
if(!ReadArgs(PARAM, (LONG *) &args, rda))
End(RETURN_FAIL);
if(!(in.file = Open(args.INFILE, MODE_OLDFILE)))
{
sprintf(filename, "%s" FDFILEEXTENSION, args.INFILE);
if(*args.SPECIAL == 200 || !(in.file = Open(filename, MODE_OLDFILE)))
{
DoError(ERR_OPEN_FILE, 0, args.INFILE);
End(RETURN_FAIL);
}
else
args.INFILE = filename;
}
VPrintf("SourceFile: %s\n", &args.INFILE);
/* OS39 and up may use AllocPooled instead of normal AllocMem. If this
fails, we use normal method */
if(SysBase->LibNode.lib_Version >= 39)
mempool = CreatePool(MEMF_ANY|MEMF_CLEAR,10240,2048);
if(!(fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)) ||
!ExamineFH(in.file, fib) ||
!(in.buf = in.pos = AllocListMem((in.size = fib->fib_Size)+1)) ||
Read(in.file, in.buf, in.size) != in.size ||
!(out.buf = out.pos = AllocListMem(out.size)) ||
!(tempbuf = AllocListMem(TEMPSIZE)))
End(RETURN_FAIL);
else
{
STRPTR ptr = FilePart(args.INFILE);
LONG len = strlen(ptr) - sizeof(FDFILEEXTENSION) + 1;
if(len >= 0 && !stricmp(ptr+len, FDFILEEXTENSION))
ShortBaseName = DupString(ptr, len);
}
MakeLines(in.pos, in.size);
if(args.EXTERNC) Flags ^= FLAG_EXTERNC;
if(args.STORMFD) Flags ^= FLAG_STORMFD;
if(args.PRIVATE) Flags ^= FLAG_PRIVATE;
if(args.NEWSYNTAX) Flags ^= FLAG_NEWSYNTAX;
if(args.SMALLDATA) Flags ^= FLAG_SMALLDATA;
if(args.USESYSCALL) Flags ^= FLAG_SYSCALL;
if(args.OPT040) Flags ^= FLAG_NOMOVEM;
if(args.NOFPU) Flags ^= FLAG_NOFPU;
if(args.FPUONLY) Flags ^= FLAG_FPUONLY;
if(args.NOPPC) Flags ^= FLAG_NOPPC;
if(args.NOSYMBOL) Flags ^= FLAG_NOSYMBOL;
if(args.PPCONLY) Flags ^= FLAG_PPCONLY;
if(args.SECTION) Flags ^= FLAG_ASMSECTION;
if(args.COMMENT && !args.SORTED)
Flags ^= FLAG_DOCOMMENT;
if(args.TO)
{
if((lock = Lock(args.TO, SHARED_LOCK)) && Examine(lock, fib) &&
fib->fib_DirEntryType > 0)
args.TO = 0;
else if(lock)
{
UnLock(lock);
lock = 0;
}
}
if(*args.SPECIAL == 200)
{
STRPTR ptr = FilePart(args.INFILE), ptr2;
for(ptr2 = ptr; *ptr2 && *ptr2 != '_' && *ptr2 != '.'; ++ptr2)
;
if(ptr2 != ptr)
{
ShortBaseName = ptr;
*ptr2 = '\0';
}
if(lock)
oldfh = CurrentDir(lock);
if(!CreateFDFile(args.TO))
End(RETURN_FAIL);
End(RETURN_OK);
}
Close(in.file);
if((in.file = Open(EXTTYPESFILE, MODE_OLDFILE)) ||
(in.file = Open(EXTTYPESFILE2, MODE_OLDFILE)))
{
STRPTR ptr;
if(ExamineFH(in.file, fib) && (ptr = AllocListMem(fib->fib_Size)) &&
Read(in.file, ptr, fib->fib_Size) == fib->fib_Size)
{
ULONG i;
if((i = ScanTypes(ptr, fib->fib_Size)) > 0)
DoError(ERR_WRONG_TYPES_LINE, i);
if(i)
End(RETURN_FAIL);
}
else
End(RETURN_FAIL);
Close(in.file); in.file = 0;
}
if(args.CLIB)
{
if(!(in.file = Open(args.CLIB, MODE_OLDFILE)))
{
sprintf(filename, "%s_protos.h", args.CLIB);
if(!(in.file = Open(filename, MODE_OLDFILE)))
{
DoError(ERR_OPEN_FILE, 0, args.CLIB);
End(RETURN_FAIL);
}
}
if(!ExamineFH(in.file, fib) ||
!(clibbuf = AllocListMem((clibsize = fib->fib_Size + 1))) ||
Read(in.file, clibbuf, fib->fib_Size) != fib->fib_Size)
End(RETURN_FAIL);
ScanClibFile(clibbuf, clibbuf+fib->fib_Size);
Close(in.file); in.file = 0;
}
if(lock)
oldfh = CurrentDir(lock);
if(!ScanFDFile())
End(RETURN_FAIL);
if(args.SORTED)
SortFDList();
if(!ShortBaseName)
{
DoError(ERR_MISSING_SHORTBASENAME, 0); End(RETURN_FAIL);
}
else if((ShortBaseNameUpper = DupString(ShortBaseName,
strlen(ShortBaseName))))
{
STRPTR a = ShortBaseNameUpper;
while((*a = toupper(*a))) /* Convert to uppercase */
a++;
}
else
End(RETURN_FAIL);
if(*args.SPECIAL < 10) /* the pragma area is up to 9 */
{
STRPTR amicall = 0, libcall = 0, amitags = 0, libtags = 0;
mode = MODUS_PRAGMA;
sprintf(filename, "%s_lib.h", ShortBaseName);
if(!args.LIBTAGS && !args.AMITAGS && !args.LIBCALL && !args.AMICALL &&
!*args.SPECIAL)
*args.SPECIAL = 6; /* default mode */
switch(*args.SPECIAL)
{
case 0: break;
case 1: pragmode = PRAGMODE_PRAGSLIB; amicall = ""; break;
case 2: sprintf(filename, "%s_pragmas.h", ShortBaseName);
pragmode = PRAGMODE_PRAGSPRAGS; libcall = ""; break;
case 3: sprintf(filename, "%s_pragmas.h", ShortBaseName);
pragmode = PRAGMODE_PRAGSPRAGS; libcall = "";
libtags = "def " TEXT_SAS_60; break;
case 4: amicall = ""; break;
case 5: amicall = amitags = ""; break;
case 7: Flags |= FLAG_GNUPRAG; /* no break ! */
case 6: amicall = " defined(" TEXT_AZTEC ") || defined("
TEXT_MAXON ") || defined(" TEXT_STORM ")";
libcall = " defined(" TEXT_DICE ") || defined(" TEXT_SAS ")";
libtags = "def " TEXT_SAS_60; amitags ="def " TEXT_STORM; break;
case 8: sprintf(filename, "%s_pragmas.h", ShortBaseName);
Flags |= FLAG_GNUPRAG; pragmode = PRAGMODE_PRAGSPRAGS; break;
default: mode = MODUS_ERROR; break;
}
if(!args.AMICALL) args.AMICALL = amicall;
if(!args.LIBCALL) args.LIBCALL = libcall;
if(!args.AMITAGS) args.AMITAGS = amitags;
if(!args.LIBTAGS) args.LIBTAGS = libtags;
if(args.MODE && *args.MODE > 0 && *args.MODE < 5)
pragmode = *args.MODE;
}
else if(*args.SPECIAL < 20) /* the misc area is up to 19 */
{
if(args.MODE && *args.MODE > 0 && *args.MODE < 4)
callmode = *args.MODE - 1;
switch(*args.SPECIAL)
{
case 10: mode = MODUS_CSTUB;
sprintf(filename, "%s_cstub.h", ShortBaseName); break;
case 11: mode = MODUS_STUBTEXT;
sprintf(filename, "%s_stub.s", ShortBaseName); break;
case 12: mode = MODUS_STUBCODE;
sprintf(filename, "%s.lib", ShortBaseName); break;
case 13: Flags |= FLAG_LOCALREG; /* no break ! */
case 14: mode = MODUS_LOCALDATA;
sprintf(filename, "%s_loc.h", ShortBaseName); args.TO = 0; break;
case 15: mode = MODUS_STUBTEXT; callmode = TAGMODE_NORMAL;
Flags ^= FLAG_PASCAL;
sprintf(filename, "%s_stub.s", ShortBaseName); break;
case 16: mode = MODUS_STUBCODE; callmode = TAGMODE_NORMAL;
Flags ^= FLAG_PASCAL;
sprintf(filename, "%s.lib", ShortBaseName); break;
case 17: mode = MODUS_BMAP; callmode = TAGMODE_NORMAL;
sprintf(filename, "%s.bmap", ShortBaseName); break;
default: mode = MODUS_ERROR; break;
}
}
else if(*args.SPECIAL < 30) /* the lvo area is up to 29 */
{
switch(*args.SPECIAL)
{
case 20: case 22: mode = MODUS_LVO+*args.SPECIAL-20;
sprintf(filename, "%s_lvo.i", ShortBaseName); break;
case 21: case 23: mode = MODUS_LVO+*args.SPECIAL-20;
sprintf(filename, "%s_lib.i", ShortBaseName); break;
case 24: mode = MODUS_LVOLIB;
sprintf(filename, "%s.lib", ShortBaseName); break;
default: mode = MODUS_ERROR; break;
}
}
else if(*args.SPECIAL < 40) /* the proto area is up to 39 */
{
if(*args.SPECIAL < 38)
{
mode = MODUS_PROTO+*args.SPECIAL-30+1;
sprintf(filename, "%s.h", ShortBaseName);
}
else
mode = MODUS_ERROR;
}
else if(*args.SPECIAL < 50) /* the inline area is up to 49 */
{
if(args.MODE && *args.MODE > 0 && *args.MODE < 4)
callmode = *args.MODE - 1;
switch(*args.SPECIAL)
{
case 40: case 41: case 42: mode = MODUS_INLINE+*args.SPECIAL-40;
sprintf(filename, "%s.h", ShortBaseName); break;
default: mode = MODUS_ERROR; break;
}
}
else if(*args.SPECIAL < 60) /* the PowerUP area is up to 59 */
{
if(args.MODE && *args.MODE > 0 && *args.MODE < 4)
callmode = *args.MODE - 1;
switch(*args.SPECIAL)
{
case 50: case 51: case 52: mode = MODUS_INLINE+*args.SPECIAL-50;
sprintf(filename, "%s.h", ShortBaseName); Flags |= FLAG_POWERUP;
break;
case 53:
sprintf(filename, "%s_pragmas.h", ShortBaseName);
mode = MODUS_SASPOWER; break;
case 54:
sprintf(filename, "%s.h", ShortBaseName);
mode = MODUS_PROTOPOWER; break;
default: mode = MODUS_ERROR; break;
}
}
else if(*args.SPECIAL < 70) /* the PASCAL stuff */
{
if(*args.SPECIAL == 60)
{
mode = MODUS_PASCAL;
sprintf(filename, "%s.pas", ShortBaseName);
}
else
mode = MODUS_ERROR;
}
else if(*args.SPECIAL < 80) /* the VBCC stuff */
{
if(args.MODE && *args.MODE > 0 && *args.MODE < 4)
callmode = *args.MODE - 1;
switch(*args.SPECIAL)
{
case 70: mode = MODUS_VBCCINLINE;
sprintf(filename, "%s.h", ShortBaseName); break;
case 71: case 72: case 75:
mode = MODUS_VBCC+*args.SPECIAL-71;
sprintf(filename, "%s_stub.s", ShortBaseName); break;
case 73: case 74:
mode = MODUS_VBCC+*args.SPECIAL-71;
sprintf(filename, "%s.lib", ShortBaseName); break;
case 76:
mode = MODUS_VBCCPUPLIB;
sprintf(filename, "lib%s.a", ShortBaseName); break;
default: mode = MODUS_ERROR; break;
}
}
if(!mode)
{
SetIoErr(ERROR_REQUIRED_ARG_MISSING);
End(RETURN_FAIL);
}
else if(mode == MODUS_ERROR)
{
SetIoErr(ERROR_TOO_MANY_ARGS);
End(RETURN_FAIL);
}
/* These modes need BaseName always. */
if(!BaseName && (mode == MODUS_PRAGMA || mode == MODUS_STUBTEXT ||
mode == MODUS_STUBCODE))
{
DoError(ERR_MISSING_BASENAME, 0); End(RETURN_FAIL);
}
if(!args.TO)
args.TO = filename;
if(args.HEADER)
{
if(!*args.HEADER || (!args.HEADER[1] && *args.HEADER=='@'))
args.HEADER = args.TO;
if(!(in.file = Open(args.HEADER, MODE_OLDFILE)) ||
!ExamineFH(in.file, fib) ||
!(HEADER = AllocListMem((headersize = fib->fib_Size)+1)) ||
Read(in.file, HEADER, headersize) != headersize)
End(RETURN_FAIL);
if(args.HEADER == args.TO)
FindHeader();
Close(in.file);
in.file = 0;
}
if(!(out.file = Open(args.TO, MODE_NEWFILE)))
End(RETURN_FAIL);
SetIoErr(0);
/* from here mode is used as return result */
if(mode >= MODUS_VBCC)
mode = CreateVBCC(mode-MODUS_VBCC, callmode);
else if(mode >= MODUS_INLINE)
mode = CreateInline(mode-MODUS_INLINE, callmode);
else if(mode >= MODUS_PROTO)
mode = CreateProtoFile(mode-MODUS_PROTO);
else if(mode >= MODUS_LVO)
mode = CreateLVOFile(mode-MODUS_LVO+1);
else if(mode == MODUS_LVOLIB)
mode = CreateLVOLib();
else if(mode == MODUS_VBCCPUPLIB)
mode = CreateVBCCPUPLib(callmode);
else if(mode == MODUS_VBCCINLINE)
mode = CreateVBCCInline();
else if(mode == MODUS_PASCAL)
mode = CreateFPCUnit();
else if(mode == MODUS_BMAP)
mode = CreateBMAP();
else if(mode == MODUS_PROTOPOWER)
mode = CreateProtoPowerUP();
else if(mode == MODUS_SASPOWER)
mode = CreateSASPowerUP(callmode);
else if(mode == MODUS_CSTUB)
mode = CreateCSTUBSFile();
else if(mode == MODUS_PRAGMA)
mode = CreatePragmaFile(args.AMICALL, args.LIBCALL, args.AMITAGS, args.LIBTAGS, pragmode);
else if(mode == MODUS_LOCALDATA)
mode = CreateLocalData(args.TO, callmode, clibbuf, clibsize);
else if(mode) /* MODUS_STUBTEXT starts with 1 */
mode = CreateAsmStubs(mode, callmode);
CloseDest(args.TO);
if(CTRL_C)
DoError(ERR_USER_ABORT, 0);
else if(!mode)
{
DoError(Output_Error ? ERR_UNKNOWN_ERROR : ERR_WRITING_FILE, 0);
End(RETURN_FAIL);
}
End(RETURN_OK);
}
void End(ULONG err)
{
if(err && !(Flags & FLAG_DIDERROR))
PrintFault(IoErr(), 0);
if(fib)
FreeDosObject(DOS_FIB, fib);
if(in.file)
Close(in.file);
if(lock)
{
CurrentDir(oldfh);
UnLock(lock);
}
if(mempool) /* free allocated pool and all entries */
DeletePool(mempool);
if(remember) /* free remember list */
{
struct RememberMem *r, *s;
r = remember;
while(r)
{
s = r;
r = r->rm_Next;
FreeMem(s, s->rm_Size);
}
}
if(rda)
{
FreeArgs(rda);
FreeDosObject(DOS_RDARGS, rda);
}
exit(err);
}